From 4520c2c6e5112fd5918bf5fa87407929d08e6441 Mon Sep 17 00:00:00 2001 From: "kunming.wang" Date: Wed, 9 Jul 2025 16:48:31 +0800 Subject: [PATCH 01/13] ports/quectel: Add new port quectel. --- ports/quectel/Makefile | 152 ++ ports/quectel/README.md | 136 + ports/quectel/boards/EC600UCN_LB/board.json | 19 + .../boards/EC600UCN_LB/mpconfigboard.h | 1 + .../boards/EC600UCN_LB/mpconfigvariant.mk | 2 + ports/quectel/boards/EG915UEC_AC/board.json | 19 + .../boards/EG915UEC_AC/mpconfigboard.h | 1 + .../boards/EG915UEC_AC/mpconfigvariant.mk | 2 + ports/quectel/boards/deploy.md | 3 + ports/quectel/boards/manifest.py | 2 + ports/quectel/callbackdeal.c | 885 ++++++ ports/quectel/callbackdeal.h | 389 +++ ports/quectel/gccollect.c | 120 + ports/quectel/gccollect.h | 41 + ports/quectel/help.c | 44 + ports/quectel/machine_extint.c | 734 +++++ ports/quectel/machine_hw_spi.c | 265 ++ ports/quectel/machine_i2c.h | 90 + ports/quectel/machine_iic.c | 188 ++ ports/quectel/machine_pin.c | 333 +++ ports/quectel/machine_rtc.c | 228 ++ ports/quectel/machine_timer.c | 311 +++ ports/quectel/machine_uart.c | 492 ++++ ports/quectel/machine_wdt.c | 101 + ports/quectel/main.c | 312 +++ ports/quectel/misc_adc.c | 119 + ports/quectel/misc_power.c | 107 + ports/quectel/misc_pwm.c | 390 +++ ports/quectel/misc_usbnet.c | 213 ++ ports/quectel/moddatacall.c | 833 ++++++ ports/quectel/moddatacall.h | 42 + ports/quectel/moddev.c | 288 ++ ports/quectel/modexample.c | 127 + ports/quectel/modflashdev.c | 181 ++ ports/quectel/modfota.c | 446 +++ ports/quectel/modhelios.c | 57 + ports/quectel/modmachine.c | 113 + ports/quectel/modmachine.h | 53 + ports/quectel/modmisc.c | 253 ++ ports/quectel/modmisc.h | 48 + ports/quectel/modnet.c | 2423 +++++++++++++++++ ports/quectel/modostimer.c | 167 ++ ports/quectel/modsim.c | 1128 ++++++++ ports/quectel/modsim.h | 222 ++ ports/quectel/modsocket.c | 1280 +++++++++ ports/quectel/modules/_boot.py | 144 + ports/quectel/modules/app_fota.py | 33 + ports/quectel/modules/app_fota_download.py | 212 ++ ports/quectel/modules/app_fota_mount.py | 49 + ports/quectel/modules/app_fota_updater.py | 91 + ports/quectel/modules/checkNet.py | 231 ++ ports/quectel/modules/checksum.py | 157 ++ ports/quectel/modules/dataCall.py | 284 ++ ports/quectel/modules/file_crc32.py | 45 + ports/quectel/modules/log.py | 119 + ports/quectel/modules/ql_fs.py | 137 + ports/quectel/modules/queue.py | 51 + ports/quectel/modules/request.py | 470 ++++ ports/quectel/modules/umqtt.py | 776 ++++++ ports/quectel/moduos.c | 240 ++ ports/quectel/modussl_mbedtls.c | 600 ++++ ports/quectel/modutime.c | 220 ++ ports/quectel/mpconfigport.h | 241 ++ ports/quectel/mpconfigport.mk | 51 + ports/quectel/mphalport.c | 384 +++ ports/quectel/mphalport.h | 88 + ports/quectel/mpthreadport.c | 334 +++ ports/quectel/mpthreadport.h | 71 + ports/quectel/plat.mk | 9 + ports/quectel/qstrdefsport.h | 2 + ports/quectel/quectel.mk | 422 +++ ports/quectel/utime_mphal.c | 110 + ports/quectel/utime_mphal.h | 43 + 73 files changed, 18974 insertions(+) create mode 100644 ports/quectel/Makefile create mode 100644 ports/quectel/README.md create mode 100644 ports/quectel/boards/EC600UCN_LB/board.json create mode 100644 ports/quectel/boards/EC600UCN_LB/mpconfigboard.h create mode 100644 ports/quectel/boards/EC600UCN_LB/mpconfigvariant.mk create mode 100644 ports/quectel/boards/EG915UEC_AC/board.json create mode 100644 ports/quectel/boards/EG915UEC_AC/mpconfigboard.h create mode 100644 ports/quectel/boards/EG915UEC_AC/mpconfigvariant.mk create mode 100644 ports/quectel/boards/deploy.md create mode 100644 ports/quectel/boards/manifest.py create mode 100644 ports/quectel/callbackdeal.c create mode 100644 ports/quectel/callbackdeal.h create mode 100644 ports/quectel/gccollect.c create mode 100644 ports/quectel/gccollect.h create mode 100644 ports/quectel/help.c create mode 100644 ports/quectel/machine_extint.c create mode 100644 ports/quectel/machine_hw_spi.c create mode 100644 ports/quectel/machine_i2c.h create mode 100644 ports/quectel/machine_iic.c create mode 100644 ports/quectel/machine_pin.c create mode 100644 ports/quectel/machine_rtc.c create mode 100644 ports/quectel/machine_timer.c create mode 100644 ports/quectel/machine_uart.c create mode 100644 ports/quectel/machine_wdt.c create mode 100644 ports/quectel/main.c create mode 100644 ports/quectel/misc_adc.c create mode 100644 ports/quectel/misc_power.c create mode 100644 ports/quectel/misc_pwm.c create mode 100644 ports/quectel/misc_usbnet.c create mode 100644 ports/quectel/moddatacall.c create mode 100644 ports/quectel/moddatacall.h create mode 100644 ports/quectel/moddev.c create mode 100644 ports/quectel/modexample.c create mode 100644 ports/quectel/modflashdev.c create mode 100644 ports/quectel/modfota.c create mode 100644 ports/quectel/modhelios.c create mode 100644 ports/quectel/modmachine.c create mode 100644 ports/quectel/modmachine.h create mode 100644 ports/quectel/modmisc.c create mode 100644 ports/quectel/modmisc.h create mode 100644 ports/quectel/modnet.c create mode 100644 ports/quectel/modostimer.c create mode 100644 ports/quectel/modsim.c create mode 100644 ports/quectel/modsim.h create mode 100644 ports/quectel/modsocket.c create mode 100644 ports/quectel/modules/_boot.py create mode 100644 ports/quectel/modules/app_fota.py create mode 100644 ports/quectel/modules/app_fota_download.py create mode 100644 ports/quectel/modules/app_fota_mount.py create mode 100644 ports/quectel/modules/app_fota_updater.py create mode 100644 ports/quectel/modules/checkNet.py create mode 100644 ports/quectel/modules/checksum.py create mode 100644 ports/quectel/modules/dataCall.py create mode 100644 ports/quectel/modules/file_crc32.py create mode 100644 ports/quectel/modules/log.py create mode 100644 ports/quectel/modules/ql_fs.py create mode 100644 ports/quectel/modules/queue.py create mode 100644 ports/quectel/modules/request.py create mode 100644 ports/quectel/modules/umqtt.py create mode 100644 ports/quectel/moduos.c create mode 100644 ports/quectel/modussl_mbedtls.c create mode 100644 ports/quectel/modutime.c create mode 100644 ports/quectel/mpconfigport.h create mode 100644 ports/quectel/mpconfigport.mk create mode 100644 ports/quectel/mphalport.c create mode 100644 ports/quectel/mphalport.h create mode 100644 ports/quectel/mpthreadport.c create mode 100644 ports/quectel/mpthreadport.h create mode 100644 ports/quectel/plat.mk create mode 100644 ports/quectel/qstrdefsport.h create mode 100644 ports/quectel/quectel.mk create mode 100644 ports/quectel/utime_mphal.c create mode 100644 ports/quectel/utime_mphal.h diff --git a/ports/quectel/Makefile b/ports/quectel/Makefile new file mode 100644 index 0000000000000..39f6f6dbcfe1e --- /dev/null +++ b/ports/quectel/Makefile @@ -0,0 +1,152 @@ +TOP := ../.. +ROOT := $(TOP)/../.. + +include ../../py/mkenv.mk +include mpconfigport.mk +include quectel.mk + +include ../../py/verbose.mk + +# 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 RPI_PICO. +BOARD ?= EC600UCN_LB +BOARD_DIR ?= boards/$(BOARD) +endif + +ifeq ($(wildcard $(BOARD_DIR)/.),) +ifeq ($(findstring boards/PICO,$(BOARD_DIR)),boards/PICO) +$(warning The PICO* boards have been renamed to RPI_PICO*) +endif +$(error Invalid BOARD specified: $(BOARD_DIR)) +endif + +# If the build directory is not given, make it reflect the board name (and +# optionally the board variant). +ifneq ($(BOARD_VARIANT),) +BUILD ?= build-$(BOARD)-$(BOARD_VARIANT) +else +BUILD ?= build-$(BOARD) +endif + +ifeq ($(BUILD_VERBOSE),1) +MAKE_ARGS += VERBOSE=1 # Picked up in Makefile generated by CMake +endif + +MAKE_ARGS += -DMICROPY_BOARD=$(BOARD) -DMICROPY_BOARD_DIR="$(abspath $(BOARD_DIR))" + +ifdef USER_C_MODULES +MAKE_ARGS += -DUSER_C_MODULES=${USER_C_MODULES} +endif + +ifneq ($(FROZEN_MANIFEST),) +MAKE_ARGS += -DMICROPY_FROZEN_MANIFEST=${FROZEN_MANIFEST} +endif + +ifeq ($(DEBUG),1) +MAKE_ARGS += -DCMAKE_BUILD_TYPE=Debug +endif + +ifdef BOARD_VARIANT +MAKE_ARGS += -DMICROPY_BOARD_VARIANT=$(BOARD_VARIANT) +endif + +ifdef MICROPY_PREVIEW_VERSION_2 +MAKE_ARGS += -DMICROPY_PREVIEW_VERSION_2=1 +endif + +FROZEN_MANIFEST ?= boards/manifest.py + +CFLAGS = $(INC) $(QUEC_MOD_CFLAGS) $(PLAT_CFLAGS) $(PLAT_DFLAGS) $(COPT) $(MAKE_ARGS) + +CSUPEROPT = -Os # save some code space + +# qstr definitions (must come before including py.mk) +QSTR_DEFS = qstrdefsport.h + +# MicroPython feature configurations +MICROPY_ROM_TEXT_COMPRESSION ?= 1 + +# include py core make definitions +include $(TOP)/py/py.mk +include $(TOP)/extmod/extmod.mk + +CROSS_COMPILE ?= arm-none-eabi- + + +INC += -I. +INC += -I$(TOP) +INC += -I$(BUILD) +INC += $(MICROPYTHON_CFLAGS_INC) +INC += $(QUEC_INC) + +# Tune for Debugging or Optimization +ifeq ($(DEBUG), 1) +CFLAGS += -O0 -ggdb +else +CFLAGS += -Os -DNDEBUG +CFLAGS += -fdata-sections -ffunction-sections +endif + +# Flags for optional C++ source code +CXXFLAGS += $(filter-out -std=c99,$(CFLAGS)) +CXXFLAGS += $(CXXFLAGS_MOD) + +# Flags for user C modules +CFLAGS += $(CFLAGS_MOD) +LDFLAGS += $(LDFLAGS_MOD) + +LIBS = + +SHARED_SRC_C = shared/libc/printf.c \ + shared/readline/readline.c \ + shared/runtime/pyexec.c \ + shared/runtime/sys_stdio_mphal.c \ + shared/runtime/stdout_helpers.c \ + shared/netutils/netutils.c \ + shared/runtime/interrupt_char.c \ + shared/timeutils/timeutils.c + +EXTMOD_SRC_C = extmod/vfs.c \ + extmod/vfs_lfs.c \ + extmod/vfs_blockdev.c \ + extmod/modrandom.c \ + extmod/modjson.c \ + extmod/modbinascii.c \ + extmod/vfs_reader.c \ + extmod/modre.c \ + extmod/modhashlib.c \ + extmod/moductypes.c + +EXTMOD_SRC_C += $(SRC_THIRDPARTY_C) + +SRC_MOD += $(QUEC_SRC_MOD) + +SRC_C += $(SRC_MOD) \ + $(SHARED_SRC_C) \ + $(EXTMOD_SRC_C) \ + $(QUEC_SRC) \ + $(BUILD)/frozen_content.c + +SRC_CXX += $(SRC_MOD_CXX) + +SRC_QSTR += $(SRC_MOD) $(SRC_MOD_CXX) $(SHARED_SRC_C) $(EXTMOD_SRC_C) + +OBJ += $(PY_CORE_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_CXX:.cpp=.o)) + +all: $(BUILD)/firmware.a + +$(BUILD)/_frozen_mpy.c: frozentest.mpy $(BUILD)/genhdr/qstrdefs.generated.h + $(ECHO) "MISC freezing bytecode" + $(Q)$(PYTHON) $(TOP)/tools/mpy-tool.py -f -q $(BUILD)/genhdr/qstrdefs.preprocessed.h -mlongint-impl=none $< > $@ + +$(BUILD)/firmware.a: $(OBJ) + $(ECHO) "AR $@" + $(Q)$(AR) -cr $@ $^ + +include $(TOP)/py/mkrules.mk diff --git a/ports/quectel/README.md b/ports/quectel/README.md new file mode 100644 index 0000000000000..a0fcb3dd74944 --- /dev/null +++ b/ports/quectel/README.md @@ -0,0 +1,136 @@ +MicroPython port to the Quectel +============================= + +This is a port of MicroPython to the Quectel series of +microcontrollers. It uses the HeliosSDK and MicroPython runs as +a task under FreeRTOS. + +Support Eigencomm, Unisoc, Qualcomm and ASR cellular modules. + +Supported features include: +- REPL (Python prompt) over usb. +- Python 3.4 syntax and built-in rich functional modules. +- The machine module with GPIO, EXTINT, UART, SPI, ADC, WDT RTC, and Timer. +- The network module with cellular modem support. +- etc. + +Setting up HeliosSDK and the build environment +-------------------------------------------- + +MicroPython on quectel port requires the HeliosSDK. The HeliosSDK includes the libraries and RTOS needed to +manage the quectel microcontroller, as well as a way to manage the required +build environment and toolchains needed to build the firmware. + +To install the HeliosSDK the full instructions can be found at the +[HeliosSDK Development Guide](https://python.quectel.com/doc/Application_guide/zh/helios-sdk/quick-start.html). + +**Windows 10 Environment Setup** + +*Step 1: Download Toolchain* + +Download the toolchain installation package [helios-toolchain.exe](https://github.com/QuecPython/toolchain/releases/tag/V1.4.2) for Windows 10 environment from the QuecPython official website. + +*Step 2: Install Toolchain* + +Run helios-toolchain.exe as an administrator, as shown in the following figure, and click "**Install**" to install the toolchain. + +> The target folder **must not** contain spaces. + +**Ubuntu Environment Setup** + +*Step 1: Download Toolchain* + +Download the toolchain installation package [helios-toolchain](https://github.com/QuecPython/toolchain/releases/tag/V1.1.0) for Ubuntu 16.04 environment from the QuecPython official website. + +*Step 2: Install Toolchain* + +Place the installation package in the same location as the target folder. Execute the following command to install the toolchain. +`sudo ./helios-toolchain` + +*Step 3: Install Other Tools* + +Enter the following command in the terminal to install `p7zip-full`, `git`, `make`, and `python3`. +``` +sudo apt install p7zip-full git make python3 +``` + +*Source Code* + +For HeliosSDK, please contact the [QuecPython technical team](https://python.quectel.com/en/contact) for the source code of HeliosSDK(We are preparing to open source), You can also get supports through email QuecPython@quectel.com. + +For MicroPython, You can directly pull the official code, but you need to pull MicroPython into the heliossdk directory, for example, create a services directory under heliossdk and place MicroPython in the services directory. + +Building the firmware +--------------------- + +Before you start building the firmware, you must build the MicroPython cross compiler firstly, it will be used to pre-compile some of the built-in scripts to bytecode. + +> If you are in a Windows environment, you need a Windows compilation toolchain, such as MinGW. + +```bash +# path: heliossdk/services/micropython +$ make -C mpy-cross +``` + +Then to build MicroPython for the quectel run: + +```bash +# path: heliossdk/services/micropython +$ cd ports/quectel +$ make submodules +$ make +``` + +This will produce a combined `firmware.a` lib in the `build/` +subdirectory directly.The compiled MicroPython library will be used by HeliosSDK to build a complete firmware package. Of course, you can also build the entire firmware directly using the following method. + +*Check the usage of the helios compilation commands* + +In the command line started in the HeliosSDK directory, type `helios` and press "**Enter**" to view the usage of the helios command. +The output is as follows: + +``` +Usage: helios [] [] [] + +These are common commands used in various situations: + menuconfig - Do the project configuration + make [[] []] - Do the compilation work + private_clean - Clean the app private target + clean - Clean the output directory + git [] - Git commands execution + help - Show this help page +``` + +> For detailed usage of the compilation command, please refer to `README.MD` in the SDK root directory. + +*Compile the firmware* + +Taking the EG915UEC_AC module as an example, type the following command in the command line and press "**Enter**": +``` +helios make services/micropython @EG915UEC_AC EG915UECACR03A01M08 +``` + +- `helios`: Trigger the compilation process. +- `make`: Compile the firmware. +- `services/micropython`: Application entry address (relative to the SDK root directory, according to the requirements of the host system, the Win32 platform is \ and the Linux platform is /). It can be adjusted according to the specific location of MicroPython. +- `@EG915UEC_AC`: Specify the target module model. You need to modify it according to your actual model. +- `EG915UECACR03A01M08`: Firmware version name, which can be omitted. You need to modify it according to your actual model. + +*Check the compilation target* + +The generated firmware package is stored in the *`output/release`* folder in the HeliosSDK root directory. + +To clean the compilation target, type the following command in the command line and press "**Enter**": +``` +helios clean +``` + +*Flash the firmware* + +You need to use QPYcom or VSCode tool to burn the firmware. Please refer to [Quectel_QFlash_User_Guide](https://python.quectel.com/doc/Getting_started/en/flash_firmware.html) for firmware flashing. + + +Accessing the board +------------------------------------- + +You can access via the `USB REPL` port, which stands for `Read-Eval-Print-Loop` (interactive interpreter). Please refer to [Quectel_Getting_Started](https://python.quectel.com/doc/Getting_started/en/REPL_dev.html) for firmware debugging. diff --git a/ports/quectel/boards/EC600UCN_LB/board.json b/ports/quectel/boards/EC600UCN_LB/board.json new file mode 100644 index 0000000000000..3edacaf108c01 --- /dev/null +++ b/ports/quectel/boards/EC600UCN_LB/board.json @@ -0,0 +1,19 @@ +{ + "deploy": [ + "../deploy.md" + ], + "docs": "", + "features": [ + "Celluar network", + "bsp", + "USB" + ], + "images": [ + "ec600ucn_lb.jpg" + ], + "mcu": "ec600ucnlb", + "product": "EC600UCN_LB", + "thumbnail": "", + "url": "https://developer.quectel.com/modules-cat/ec600u-series", + "vendor": "Unisoc" +} diff --git a/ports/quectel/boards/EC600UCN_LB/mpconfigboard.h b/ports/quectel/boards/EC600UCN_LB/mpconfigboard.h new file mode 100644 index 0000000000000..6b68f6af78f16 --- /dev/null +++ b/ports/quectel/boards/EC600UCN_LB/mpconfigboard.h @@ -0,0 +1 @@ +// Board and hardware specific configuration diff --git a/ports/quectel/boards/EC600UCN_LB/mpconfigvariant.mk b/ports/quectel/boards/EC600UCN_LB/mpconfigvariant.mk new file mode 100644 index 0000000000000..139597f9cb07c --- /dev/null +++ b/ports/quectel/boards/EC600UCN_LB/mpconfigvariant.mk @@ -0,0 +1,2 @@ + + diff --git a/ports/quectel/boards/EG915UEC_AC/board.json b/ports/quectel/boards/EG915UEC_AC/board.json new file mode 100644 index 0000000000000..24894487c2793 --- /dev/null +++ b/ports/quectel/boards/EG915UEC_AC/board.json @@ -0,0 +1,19 @@ +{ + "deploy": [ + "../deploy.md" + ], + "docs": "", + "features": [ + "Celluar network", + "bsp", + "USB" + ], + "images": [ + "eg915uec_ac.jpg" + ], + "mcu": "eg915uecac", + "product": "EG915UEC_AC", + "thumbnail": "", + "url": "https://developer.quectel.com/en/modules-cat/eg915u-series", + "vendor": "Unisoc" +} \ No newline at end of file diff --git a/ports/quectel/boards/EG915UEC_AC/mpconfigboard.h b/ports/quectel/boards/EG915UEC_AC/mpconfigboard.h new file mode 100644 index 0000000000000..6b68f6af78f16 --- /dev/null +++ b/ports/quectel/boards/EG915UEC_AC/mpconfigboard.h @@ -0,0 +1 @@ +// Board and hardware specific configuration diff --git a/ports/quectel/boards/EG915UEC_AC/mpconfigvariant.mk b/ports/quectel/boards/EG915UEC_AC/mpconfigvariant.mk new file mode 100644 index 0000000000000..139597f9cb07c --- /dev/null +++ b/ports/quectel/boards/EG915UEC_AC/mpconfigvariant.mk @@ -0,0 +1,2 @@ + + diff --git a/ports/quectel/boards/deploy.md b/ports/quectel/boards/deploy.md new file mode 100644 index 0000000000000..d23eaced8cbbb --- /dev/null +++ b/ports/quectel/boards/deploy.md @@ -0,0 +1,3 @@ +*Flash the firmware* + +You need to use QPYcom or VSCode tool to burn the firmware. Please refer to [Quectel_QFlash_User_Guide](https://python.quectel.com/doc/Getting_started/en/flash_firmware.html) for firmware flashing. diff --git a/ports/quectel/boards/manifest.py b/ports/quectel/boards/manifest.py new file mode 100644 index 0000000000000..b0b0d31a051b1 --- /dev/null +++ b/ports/quectel/boards/manifest.py @@ -0,0 +1,2 @@ +freeze("$(PORT_DIR)/modules") +include("$(MPY_DIR)/extmod/asyncio") diff --git a/ports/quectel/callbackdeal.c b/ports/quectel/callbackdeal.c new file mode 100644 index 0000000000000..dce7dcd77dc4a --- /dev/null +++ b/ports/quectel/callbackdeal.c @@ -0,0 +1,885 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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 "helios_os.h" +#include "stackctrl.h" +#include "py/runtime.h" +#include "py/gc.h" +#include "callbackdeal.h" +#include "py/obj.h" +#if MICROPY_ENABLE_CALLBACK_DEAL + + +#ifdef QPY_CALLBACKDEAL_LOG_ENABLE +#if defined(PLAT_ASR) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_ASR_1602) +extern void ql_log_mask_set(unsigned long long module_mask, unsigned int port_mask); +extern void _ql_app_log(const char* fmt, ...); +static char usb_trace_init_flag = 0; +#define qpy_callbackdeal_trace(fmt, ...) do{ \ + if(!usb_trace_init_flag) \ + { \ + ql_log_mask_set(0x20, 0x02); \ + usb_trace_init_flag = 1; \ + } \ + _ql_app_log("[%s][%s, L%d]"fmt"", "cbdl", __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + }while(0) + +#elif defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_Unisoc_8850_R02) || defined(PLAT_Unisoc_8910_R06) +#include "helios_debug.h" +#define qpy_callbackdeal_trace(fmt, ...) Helios_Debug_Output("[%s][%s, L%d]"fmt"", "cbdl", __FUNCTION__, __LINE__, ##__VA_ARGS__) +#else +#error "The platform not support usb trace!!!" +#endif +#else +#define qpy_callbackdeal_trace(fmt, ...) +#endif + + + +#define QPY_CALLBACK_DEAL_MSG_MAX_NUM (2 * MICROPY_SCHEDULER_DEPTH) +#if defined(PLAT_ECR6600) || defined (PLAT_aic8800m40) +#define QPY_CALLBACK_DEAL_THREAD_STACK_SIZE (4 *1024) +#else +#define QPY_CALLBACK_DEAL_THREAD_STACK_SIZE (16 *1024) +#endif + +static Helios_MsgQ_t qpy_callback_deal_queue = 0; +Helios_Thread_t qpy_callback_deal_task_ref = 0; + +typedef struct _callback_deal_thread_entry_args_t { + mp_obj_dict_t *dict_locals; + mp_obj_dict_t *dict_globals; +} callback_deal_thread_entry_args_t; + +#if MICROPY_QPY_MODULE_BT +extern void qpy_bt_msg_proc(void *msg); +#endif +#if MICROPY_QPY_MODULE_BLE +extern void qpy_ble_msg_proc(void *msg); +#endif + +#if MICROPY_QPY_MODULE_POC +extern void qpy_poc_msg_proc ( void *msg ); +#endif //end MICROPY_QPY_MODULE_POC + +#if MICROPY_QPY_MODULE_LWM2M +extern void qpy_lwm2m_msg_proc(void *param); +#endif //end MICROPY_QPY_MODULE_LWM2M + +#if MICROPY_QPY_MODULE_ESIM && MICROPY_QPY_MODULE_ESIM_IPA +extern void qpy_esim_msg_proc(void *param); +#endif +/* + * Create a task&queue that handles callback tasks exclusively + */ +void qpy_callback_deal_thread(void * args_in); + +/*Jayceon 2022/08/31 add for QuecPython --start*/ +extern bool mp_obj_is_boundmeth(mp_obj_t o); +extern mp_obj_t mp_obj_bound_get_self(void *bound); +extern mp_obj_t mp_obj_bound_get_meth(void *bound); +extern bool mp_obj_is_closure(void *obj); +extern mp_obj_t mp_obj_closure_get_fun(void *closure); + +typedef struct temp_mp_obj_bound_meth_t { + mp_obj_base_t base; + mp_obj_t meth; + mp_obj_t self; +} temp_mp_obj_bound_meth_t; + +typedef struct temp_mp_obj_closure_t { + mp_obj_base_t base; + mp_obj_t fun; + size_t n_closed; + mp_obj_t closed[]; +} temp_mp_obj_closure_t; + +mp_obj_t mp_obj_bound_get_self(void *bound) +{ + if(NULL == bound) + return NULL; + + return ((temp_mp_obj_bound_meth_t *)bound)->self; +} + +mp_obj_t mp_obj_bound_get_meth(void *bound) +{ + if(NULL == bound) + return NULL; + + return ((temp_mp_obj_bound_meth_t *)bound)->meth; +} + +bool mp_obj_is_boundmeth(mp_obj_t o) { + + return mp_obj_is_type(o, &mp_type_bound_meth); +} + +extern const mp_obj_type_t mp_type_closure; +bool mp_obj_is_closure(void *obj) +{ + return mp_obj_is_type(obj, &mp_type_closure); +} + +mp_obj_t mp_obj_closure_get_fun(void *closure){ + if(NULL == closure) + return NULL; + + return ((temp_mp_obj_closure_t *)closure)->fun; +} + +extern void mp_main_thread_wakeup(); +static bool _mp_sched_schedule_ex(c_callback_t *callback) { + + // When executing code within a handler we must lock the scheduler to + // prevent any scheduled callbacks from running, and lock the GC to + // prevent any memory allocations. + mp_sched_lock(); + gc_lock(); + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + mp_sched_schedule(callback->cb, callback->arg); + nlr_pop(); + } else { + // Uncaught exception; disable the callback so that it doesn't run again + mp_printf(&mp_plat_print, "Uncaught exception in IRQ callback handler\n"); + mp_obj_print_exception(MICROPY_ERROR_PRINTER, MP_OBJ_FROM_PTR(nlr.ret_val)); + gc_unlock(); + mp_sched_unlock(); + return false; + } + gc_unlock(); + mp_sched_unlock(); + + mp_main_thread_wakeup(); + return true; +} + +//Add a callback to the unscheduled table. If it is a Method, +//load it first so that the recorded callback is not collected by the GC +bool mp_sched_schedule_ex(c_callback_t *callback, mp_obj_t arg) +{ + (void)arg; + if(NULL == callback) + { + return false; + } + + if((false == callback->is_method) && mp_obj_is_callable(callback->cb))//function + { + return _mp_sched_schedule_ex(callback); + } + else if(true == callback->is_method)//bound_method + { + if(mp_obj_is_boundmeth(callback->cb)) { + return _mp_sched_schedule_ex(callback); + } else { + mp_obj_t cb = mp_load_attr(callback->method_self, callback->method_name); + callback->cb = cb;//record a new boundmeth + return _mp_sched_schedule_ex(callback); + } + } + else + { + return false; + } +} + +//Register callback +bool mp_sched_schedule_callback_register(c_callback_t *callback, mp_obj_t func_obj) +{ + if(NULL == callback || NULL == func_obj) { + return false; + } + //memset(callback, 0 , sizeof(c_callback_t)); + if(mp_const_none != func_obj) + { + if(mp_obj_is_boundmeth(func_obj))//is bound_meth. Records the object for this method, along with the bytecode for the name of this method + { + callback->is_method = true; + callback->method_self = mp_obj_bound_get_self(func_obj); + mp_obj_t fun = mp_obj_bound_get_meth((int*)func_obj); + if(mp_obj_is_closure(fun)) { + callback->method_name = mp_obj_fun_get_name(mp_obj_closure_get_fun(fun)); + } else { + callback->method_name = mp_obj_fun_get_name(fun); + } + callback->cb = func_obj; + return true; + } + } + + callback->is_method = false; + callback->cb = func_obj; + + return true; +} + +void qpy_callback_deal_init(void) +{ +#if !defined(PLAT_RDA) + qpy_callback_deal_queue = Helios_MsgQ_Create(QPY_CALLBACK_DEAL_MSG_MAX_NUM, sizeof(st_CallBack_Deal)); +#endif + // create thread + callback_deal_thread_entry_args_t *th_args; + th_args = m_new_obj(callback_deal_thread_entry_args_t); + // pass our locals and globals into the new thread + th_args->dict_locals = mp_locals_get(); + th_args->dict_globals = mp_globals_get(); + + Helios_ThreadAttr ThreadAttr = { + .name = "cb_deal", + .stack_size = QPY_CALLBACK_DEAL_THREAD_STACK_SIZE, + .priority = (MP_THREAD_PRIORITY - 2),//high than mpthread + .entry = (void*)qpy_callback_deal_thread, + .argv = (void*)th_args + }; + qpy_callback_deal_task_ref = Helios_Thread_Create(&ThreadAttr); + //add thread to python_thread link list, the thread is automatically deleted after the VM restarts. + mp_new_thread_add((uint32_t)qpy_callback_deal_task_ref, QPY_CALLBACK_DEAL_THREAD_STACK_SIZE); +} + +/* + * Returns whether the current thread is callbackdeal thread + */ +bool qpy_is_callback_deal_thread(void) +{ + return (Helios_Thread_GetID() == qpy_callback_deal_task_ref); +} + +/* + * delete callback_deal task&queue + */ +void qpy_callback_deal_deinit(void) +{ + Helios_MsgQ_Delete(qpy_callback_deal_queue); qpy_callback_deal_queue = (Helios_MsgQ_t)0; + //Just set it to null and the thread will be deleted automatically when the vm restarts + qpy_callback_deal_task_ref = (Helios_Thread_t)0; +} + + +//Added by Freddy @20211124 发送消息至deal task的queue +int qpy_send_msg_to_callback_deal_thread(uint8_t id, void *msg) +{ + int ret = -1; + if((Helios_MsgQ_t)0 != qpy_callback_deal_queue) + { + st_CallBack_Deal cb_msg = {0}; + cb_msg.callback_type_id = id; + cb_msg.msg = msg; + qpy_callbackdeal_trace("callback_type_id:%d", id); + ret = Helios_MsgQ_Put(qpy_callback_deal_queue, (void*)(&cb_msg), sizeof(st_CallBack_Deal), HELIOS_NO_WAIT); + } + return ret; +} + + +st_CallBack_LoadBoundMeth * qpy_callback_para_node_add(c_callback_t *callback, mp_obj_t arg) +{ + st_CallBack_LoadBoundMeth *loadboundmet_msg = calloc(1, sizeof(st_CallBack_LoadBoundMeth)); + if(NULL == loadboundmet_msg) + { + return NULL; + } +#if defined(PLAT_ASR) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_ASR_1602) + int rc = Helios_Critical_Enter(); +#endif + loadboundmet_msg->next = (st_CallBack_LoadBoundMeth *)MP_STATE_PORT(loadmeth_para); + loadboundmet_msg->callback = callback; + loadboundmet_msg->arg = arg; + MP_STATE_PORT(loadmeth_para) = (void *)loadboundmet_msg; + qpy_callbackdeal_trace("loadmeth_para:0x%x", MP_STATE_PORT(loadmeth_para)); +#if defined(PLAT_ASR) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_ASR_1602) + Helios_Critical_Exit(rc); +#endif + + return loadboundmet_msg; +} + + +void qpy_callback_para_node_delete(st_CallBack_LoadBoundMeth *cb_msg) +{ +#if defined(PLAT_ASR) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_ASR_1602) + int rc = Helios_Critical_Enter(); +#endif + qpy_callbackdeal_trace("loadmeth_para:0x%x", MP_STATE_PORT(loadmeth_para)); + st_CallBack_LoadBoundMeth *loadmeth_para_head = (st_CallBack_LoadBoundMeth *)MP_STATE_PORT(loadmeth_para); + st_CallBack_LoadBoundMeth *loadmeth_para_tmp = loadmeth_para_head; + for(;loadmeth_para_head != NULL; loadmeth_para_head = loadmeth_para_head->next) + { + if(loadmeth_para_head == cb_msg) + { + qpy_callbackdeal_trace("cb_msg:0x%x", cb_msg); + if(loadmeth_para_head == (st_CallBack_LoadBoundMeth *)MP_STATE_PORT(loadmeth_para)) + { + MP_STATE_PORT(loadmeth_para) = loadmeth_para_head->next; + qpy_callbackdeal_trace("loadmeth_para:0x%x", MP_STATE_PORT(loadmeth_para)); + } + else + { + loadmeth_para_tmp->next = loadmeth_para_head->next; + } + break; + } + loadmeth_para_tmp = loadmeth_para_head; + } +#if defined(PLAT_ASR) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_ASR_1602) + Helios_Critical_Exit(rc); +#endif + +} + +void qpy_callback_para_link_mark_in_used(void) +{ + +#if defined(PLAT_ASR) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_ASR_1602) + int rc = Helios_Critical_Enter(); +#endif + st_CallBack_LoadBoundMeth *loadmeth_para_head = (st_CallBack_LoadBoundMeth *)MP_STATE_PORT(loadmeth_para); + for(;loadmeth_para_head != NULL; loadmeth_para_head = loadmeth_para_head->next) + { + if(NULL != loadmeth_para_head->arg) + { + gc_collect_root((void **)&loadmeth_para_head->arg, 1); + } + } +#if defined(PLAT_ASR) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_ASR_1602) + Helios_Critical_Exit(rc); +#endif + +} + + +void qpy_callback_para_link_free_all(void) +{ +#if defined(PLAT_ASR) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_ASR_1602) + int rc = Helios_Critical_Enter(); +#endif + st_CallBack_LoadBoundMeth *loadmeth_para_head = (st_CallBack_LoadBoundMeth *)MP_STATE_PORT(loadmeth_para); + st_CallBack_LoadBoundMeth *loadmeth_para_tmp = NULL; + while(loadmeth_para_head != NULL) + { + loadmeth_para_tmp = loadmeth_para_head; + loadmeth_para_head = loadmeth_para_head->next; + free(loadmeth_para_tmp); + } + MP_STATE_PORT(loadmeth_para) = NULL; +#if defined(PLAT_ASR) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_ASR_1602) + Helios_Critical_Exit(rc); +#endif + +} + + +bool mp_sched_empty(void); +/* + * Resolve the crash issue when non-Python threads apply for GC memory and throw exceptions when memory application fails + */ +void qpy_callback_deal_thread(void * args_in) +{ +#if !defined(PLAT_RDA) + qpy_callback_deal_queue = Helios_MsgQ_Create(QPY_CALLBACK_DEAL_MSG_MAX_NUM, sizeof(st_CallBack_Deal)); +#endif + callback_deal_thread_entry_args_t *args = (callback_deal_thread_entry_args_t *)args_in; + mp_state_thread_t ts; + mp_thread_set_state(&ts); + st_CallBack_Deal msg = {0}; + + mp_stack_set_top(&ts + 1); // need to include ts in root-pointer scan +#if defined(PLAT_ECR6600) || defined (PLAT_aic8800m40) + mp_stack_set_limit(QPY_CALLBACK_DEAL_THREAD_STACK_SIZE * sizeof(uint32_t) - 1024); +#else + mp_stack_set_limit(QPY_CALLBACK_DEAL_THREAD_STACK_SIZE - 1024); +#endif + + #if MICROPY_ENABLE_PYSTACK + // TODO threading and pystack is not fully supported, for now just make a small stack + mp_obj_t mini_pystack[128]; + mp_pystack_init(mini_pystack, &mini_pystack[128]); + #endif + + // set locals and globals from the calling context + mp_locals_set(args->dict_locals); + mp_globals_set(args->dict_globals); + m_del_obj(callback_deal_thread_entry_args_t, args); + + MP_THREAD_GIL_ENTER(); + + //mp_thread_start must placed after GIL_ENTER + // signal that we are set up and running + mp_thread_start(); + + while(1) + { + mp_obj_t arg = NULL; + MP_THREAD_GIL_EXIT(); + qpy_callbackdeal_trace("wait msg"); + int ret = Helios_MsgQ_Get(qpy_callback_deal_queue, (void*)&msg, sizeof(msg), HELIOS_WAIT_FOREVER); + qpy_callbackdeal_trace("get msg"); + MP_THREAD_GIL_ENTER(); + if (ret == 0) + { + //Each is processed according to the callback ID + qpy_callbackdeal_trace("callback_type_id:%d", msg.callback_type_id); + switch(msg.callback_type_id) + { + case CALLBACK_TYPE_ID_EXTINT: + { + st_CallBack_Extint *cb_msg = (st_CallBack_Extint *)msg.msg; + mp_obj_tuple_t *pair = MP_OBJ_TO_PTR(cb_msg->callback.arg); + pair->items[0] = mp_obj_new_int(cb_msg->pin_no); + pair->items[1] = mp_obj_new_int(cb_msg->edge); + // mp_obj_t extint_list[2] = { + // mp_obj_new_int(cb_msg->pin_no), + // mp_obj_new_int(cb_msg->edge), + // }; + // arg = mp_obj_new_list(2, extint_list); + mp_sched_schedule_ex(&cb_msg->callback, cb_msg->callback.arg); + } + break; + case CALLBACK_TYPE_ID_AUDIO_RECORD: + { + st_CallBack_AudioRecord *cb_msg = (st_CallBack_AudioRecord *)msg.msg; + mp_obj_t audio_cb[3] = { + mp_obj_new_str(cb_msg->p_data,strlen(cb_msg->p_data)), + mp_obj_new_int(cb_msg->len), + mp_obj_new_int(cb_msg->res), + }; + if(RECORE_TYPE_FILE == cb_msg->record_type && NULL != cb_msg->p_data) { + free(cb_msg->p_data); + } + arg = mp_obj_new_list(3, audio_cb); + mp_sched_schedule_ex(&cb_msg->callback, arg); + #if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_Unisoc_8910_R06) + if (RECORE_TYPE_STREAM == cb_msg->record_type) + { + MP_THREAD_GIL_EXIT(); + Helios_msleep(10); + MP_THREAD_GIL_ENTER(); + } + #endif + } + break; + case CALLBACK_TYPE_ID_VOICECALL_RECORD: + { + st_CallBack_AudioRecord *cb_msg = (st_CallBack_AudioRecord *)msg.msg; + mp_obj_t audio_cb[3] = { + mp_obj_new_str(cb_msg->p_data,strlen(cb_msg->p_data)), + mp_obj_new_int(cb_msg->len), + mp_obj_new_int(cb_msg->res), + }; + + arg = mp_obj_new_list(3, audio_cb); + mp_sched_schedule_ex(&cb_msg->callback, arg); + } + break; + #if MICROPY_QPY_MODULE_QUECIOT + case CALLBACK_TYPE_ID_QUETCH_CALLCB: + { + st_CallBack_Queth cb_msg; + memcpy(&cb_msg,msg.msg,sizeof(st_CallBack_Queth)); + mp_obj_t tuple[] = + { + mp_obj_new_int_from_uint(cb_msg.event), + mp_obj_new_int_from_uint(cb_msg.errcode), + mp_obj_new_bytes(cb_msg.valueT, cb_msg.valLen) + }; + if ( cb_msg.valueT != NULL ) + free(cb_msg.valueT); + free(msg.msg); + mp_sched_schedule_ex(&(cb_msg.call_cb),mp_obj_new_tuple(3, tuple)); + } + break; + #endif //end MICROPY_QPY_MODULE_QUECIOT + #if MICROPY_QPY_MODULE_POC + case CALLBACK_TYPE_ID_POC: + { + qpy_poc_msg_proc(msg.msg); + } + break; + #endif //end MICROPY_QPY_MODULE_POC + #if MICROPY_QPY_MACHINE_KEYPAD + case CALLBACK_TYPE_ID_KEYPAD: + { + st_CallBack_Keypad *cb_msg = (st_CallBack_Keypad *)msg.msg; + mp_obj_t keypad_list[3] = + { + mp_obj_new_int(cb_msg->event_id), + mp_obj_new_int(cb_msg->row), + mp_obj_new_int(cb_msg->col), + }; + arg = mp_obj_new_list(3, keypad_list); + mp_sched_schedule_ex(&cb_msg->callback, arg); + + } + break; + #endif + #if MICROPY_QPY_SENSOR_ICC_KEY + case CALLBACK_TYPE_ID_ICCKEY: + { + st_CallBack_IccKey *cb_msg = (st_CallBack_IccKey *)msg.msg; + mp_sched_schedule_ex(&cb_msg->callback, mp_obj_new_int(cb_msg->key_event)); + } + break; + #endif + + #if MICROPY_QPY_MACHINE_KEY + case CALLBACK_TYPE_ID_KEY: + { + st_CallBack_Key *cb_msg = (st_CallBack_Key *)msg.msg; + mp_obj_t key_list[2] = { + mp_obj_new_int(cb_msg->gpio_number), + mp_obj_new_int(cb_msg->key_event), + }; + arg = mp_obj_new_list(2, key_list); + mp_sched_schedule_ex(&cb_msg->callback, arg); + } + break; + #endif + #if MICROPY_QPY_SENSOR_HANDMIC_KEY + case CALLBACK_TYPE_ID_HANDMIC_KEY: + { + st_CallBack_Handmic *cb_msg = (st_CallBack_Handmic *)msg.msg; + mp_obj_t key_list[2] = { + mp_obj_new_int(cb_msg->key_state), + mp_obj_new_int(cb_msg->key_value), + }; + arg = mp_obj_new_list(2, key_list); + mp_sched_schedule_ex(&cb_msg->callback, arg); + } + break; + #endif + #if MICROPY_QPY_MODULE_EXTUART_WK2114 + case CALLBACK_TYPE_ID_WK2114: + { + st_CallBack_Wk2114 *cb_msg = (st_CallBack_Wk2114 *)msg.msg; + mp_obj_t key_list[3] = { + mp_obj_new_int(cb_msg->int_type), + mp_obj_new_int(cb_msg->port), + mp_obj_new_int(cb_msg->read_lenth), + }; + arg = mp_obj_new_list(3, key_list); + mp_sched_schedule_ex(&cb_msg->callback, arg); + } + break; + #endif + #if MICROPY_QPY_MODULE_JRTC + case CALLBACK_TYPE_ID_JRTC: + { + st_CallBack_jrtc *cb_msg = (st_CallBack_jrtc *)msg.msg; + arg = mp_obj_new_int(cb_msg->result); + mp_sched_schedule_ex(&cb_msg->callback, arg); + + } + break; + #endif + #if MICROPY_QPY_MODULE_GPIO_ENCODER + case CALLBACK_TYPE_ID_ENCODER: + { + st_CallBack_Encoder *cb_msg = (st_CallBack_Encoder *)msg.msg; + arg = mp_obj_new_int(cb_msg->spin_direct); + mp_sched_schedule_ex(&cb_msg->callback, arg); + } + break; + #endif + #if MICROPY_QPY_MODULE_EXTGPIO_AW9523 + case CALLBACK_TYPE_ID_AW9523: + { + st_CallBack_AW9523 *cb_msg = (st_CallBack_AW9523 *)msg.msg; + mp_obj_t aw9523_list[2] = { + mp_obj_new_int(cb_msg->pin_no), + mp_obj_new_int(cb_msg->pin_level), + }; + arg = mp_obj_new_list(2, aw9523_list); + mp_sched_schedule_ex(&cb_msg->callback, arg); + } + break; + #endif + case CALLBACK_TYPE_ID_TP: + { + st_CallBack_TP *cb_msg = (st_CallBack_TP *)msg.msg; + mp_sched_schedule_ex(&cb_msg->callback, mp_obj_new_int(cb_msg->state)); + } + break; + #if MICROPY_QPY_MODULE_BT + case CALLBACK_TYPE_ID_BT: + { + qpy_bt_msg_proc(msg.msg); + break; + } + #endif + #if MICROPY_QPY_MODULE_BLE + case CALLBACK_TYPE_ID_BLE: + { + qpy_ble_msg_proc(msg.msg); + break; + } + #endif + case CALLBACK_TYPE_ID_LOAD_BOUNDMETH: + { + st_CallBack_LoadBoundMeth *cb_msg = (st_CallBack_LoadBoundMeth *)msg.msg; + qpy_callbackdeal_trace("cb_msg:0x%x", cb_msg); + qpy_callback_para_node_delete(cb_msg); + + mp_obj_t cb = mp_load_attr(cb_msg->callback->method_self, cb_msg->callback->method_name); + qpy_callbackdeal_trace("cb:0x%x", cb); + mp_call_function_1_protected(cb, cb_msg->arg); + break; + } + #if MICROPY_QPY_MODULE_ALIPAY + case CALLBACK_TYPE_ID_ALIPAY: + { + st_CallBack_ALIPAY *alipay_msg = (st_CallBack_ALIPAY *)msg.msg; + mp_obj_t alipay_cb[5] = + { + mp_obj_new_int(alipay_msg->cmd), + mp_obj_new_int(alipay_msg->rsp_code), + mp_obj_new_str((char *)(alipay_msg->result), (char *)(strlen(alipay_msg->result))), + mp_obj_new_int(alipay_msg->result_len), + mp_obj_new_str((char *)(alipay_msg->userdata), (char *)(strlen(alipay_msg->userdata))), + }; + mp_sched_schedule_ex(&alipay_msg->callback, mp_obj_new_tuple(5, alipay_cb)); + break; + } + #endif + #if MICROPY_QPY_LPM_WAKEUP + case CALLBACK_TYPE_ID_WAKEUP: + { + st_CallBack_Wakeup *cb_msg = (st_CallBack_Wakeup *)msg.msg; + mp_sched_schedule_ex(&cb_msg->callback, mp_obj_new_int(cb_msg->level)); + break; + } + #endif + #if MICROPY_QPY_MACHINE_UART + case CALLBACK_TYPE_ID_UART: + { + st_CallBack_Uart *uart_msg = (st_CallBack_Uart *)msg.msg; + // mp_obj_t uart_cb[3] = + // { + // mp_obj_new_int(uart_msg->ind_type), + // mp_obj_new_int(uart_msg->port), + // mp_obj_new_int(uart_msg->size), + // }; + // arg = mp_obj_new_list(3,uart_cb); + mp_obj_tuple_t *pair = MP_OBJ_TO_PTR(uart_msg->callback.arg); + pair->items[0] = mp_obj_new_int(uart_msg->ind_type); + pair->items[1] = mp_obj_new_int(uart_msg->port); + pair->items[2] = mp_obj_new_int(uart_msg->size); + mp_sched_schedule_ex(&uart_msg->callback, uart_msg->callback.arg); + break; + } + #endif + #if MICROPY_QPY_MODULE_NET + case CALLBACK_TYPE_ID_NET: + { + qpy_callbackdeal_trace("callback_type_id:CALLBACK_TYPE_ID_NET = %d", msg.callback_type_id); + st_CallBack_Net *net_msg = (st_CallBack_Net *)msg.msg; + mp_obj_tuple_t *pair = MP_OBJ_TO_PTR(net_msg->callback.arg); + pair->items[0] = mp_obj_new_int(net_msg->event_id); + pair->items[1] = mp_obj_new_int(net_msg->status); + pair->items[2] = mp_obj_new_int(net_msg->lac); + pair->items[3] = mp_obj_new_int(net_msg->cid); + pair->items[4] = mp_obj_new_int(net_msg->act); + + mp_sched_schedule_ex(&net_msg->callback, net_msg->callback.arg); + break; + } + #endif + #if MICROPY_QPY_MODULE_DATACALL + case CALLBACK_TYPE_ID_DATACALL: + { + st_CallBack_Datacall *datacall_msg = (st_CallBack_Datacall *)msg.msg; + mp_obj_tuple_t *pair = MP_OBJ_TO_PTR(datacall_msg->callback.arg); + pair->items[0] = mp_obj_new_int(datacall_msg->profile_idx); + pair->items[1] = mp_obj_new_int(datacall_msg->nw_status); + pair->items[2] = mp_obj_new_int(datacall_msg->sim_id); + + mp_sched_schedule_ex(&datacall_msg->callback, datacall_msg->callback.arg); + break; + } + #endif + #if MICROPY_QPY_MODULE_ALIPAY_COLLECTION + case CALLBACK_TYPE_ID_ALIPAY_COLLECTION: + { + st_CallBack_ALIPAY_COLLECTION *alipay_collection_msg = (st_CallBack_ALIPAY_COLLECTION *)msg.msg; + mp_obj_t alipay_collection_cb[2] = + { + mp_obj_new_int(alipay_collection_msg->msgID), + mp_obj_new_int(alipay_collection_msg->data), + }; + mp_sched_schedule_ex(&alipay_collection_msg->callback, mp_obj_new_tuple(2, alipay_collection_cb)); + break; + } + #endif + #if MICROPY_QPY_MODULE_SMS + case CALLBACK_TYPE_ID_SMS: + { + st_CallBack_SMS *sms_msg = (st_CallBack_SMS *)msg.msg; + mp_obj_t sms_cb[3] = + { + mp_obj_new_int(sms_msg->sim_id), + mp_obj_new_int(sms_msg->index), + mp_obj_new_str(sms_msg->storage, strlen(sms_msg->storage)) + }; + mp_sched_schedule_ex(&sms_msg->callback, mp_obj_new_tuple(3, sms_cb)); + break; + } + #endif + #if MICROPY_QPY_MODULE_SIF + case CALLBACK_TYPE_ID_SIF: + { + st_CallBack_SIF *sif_msg = (st_CallBack_SIF *)msg.msg; + mp_sched_schedule_ex(&sif_msg->callback, mp_obj_new_bytes(sif_msg->data, sif_msg->data_len)); + break; + } + #endif + #if defined(BOARD_BC32RA) || defined(BOARD_BC92RB) || defined(PLAT_SONY_ALT1350)//forrest.liu@20231228 add for FAE-102027 dump issue + #if MICROPY_QPY_MACHINE_TIMER + case CALLBACK_TYPE_ID_TIMER: + { + st_CallBack_Timer *timer_msg = (st_CallBack_Timer *)msg.msg; + + mp_sched_schedule_ex(&timer_msg->callback, mp_const_none); + break; + } + #endif + #endif + #if defined(BOARD_EC600MCN_LA_POC_XBND) || defined(BOARD_EC600MCN_LE_POC_XBND) || defined(BOARD_EC600MEU_LA_POC_XBND) \ + || defined(BOARD_EC600MLA_LA_POC_XBND) + case CALLBACK_TYPE_ID_POCSPEAK: + { + st_CallBack_PocSpeak *pocspeak_msg = (st_CallBack_PocSpeak *)msg.msg; + mp_obj_t pocspeak_list[2] = + { + mp_obj_new_int(pocspeak_msg->speak_op), + mp_obj_new_int(pocspeak_msg->speak_result), + }; + arg = mp_obj_new_list(2, pocspeak_list); + mp_sched_schedule_ex(&pocspeak_msg->callback, arg); + break; + } + #endif +#if MICROPY_QPY_MODULE_NFC + case CALLBACK_TYPE_ID_NFC: + { + st_CallBack_nfc *nfc_msg = (st_CallBack_nfc *)msg.msg; + + mp_obj_t nfc_list[2] = {0}; + nfc_list[0] = mp_obj_new_int(nfc_msg->oid); + + if(nfc_msg->data && nfc_msg->data_len != 0) + { + nfc_list[1] = mp_obj_new_bytes(nfc_msg->data, nfc_msg->data_len); + arg = mp_obj_new_list(2, nfc_list); + } else { + arg = mp_obj_new_list(1, nfc_list); + } + mp_sched_schedule_ex(&nfc_msg->callback, arg); + + if(nfc_msg->data) { + free(nfc_msg->data); + nfc_msg->data = NULL; + } + + break; + } +#endif +#if MICROPY_QPY_SENSOR_VC9202 + + case CALLBACK_TYPE_ID_VC9202: + { + st_CallBack_Sensor_VC9202 *cb_msg = (st_CallBack_Sensor_VC9202 *)msg.msg; + mp_obj_t vc9202_list[3] = { + mp_obj_new_int(cb_msg->work_mode), + mp_obj_new_int(cb_msg->value), + mp_obj_new_int(cb_msg->measure_mode), + }; + arg = mp_obj_new_list(3, vc9202_list); + mp_sched_schedule_ex(&cb_msg->callback, arg); + } + break; +#endif +#if MICROPY_QPY_MODULE_LWM2M + case CALLBACK_TYPE_ID_LWM2M:{ + qpy_lwm2m_msg_proc(msg.msg); + break; + } +#endif +#if MICROPY_QPY_MODULE_ESIM && MICROPY_QPY_MODULE_ESIM_IPA + case CALLBACK_TYPE_ID_ESIM_IPA:{ + qpy_esim_msg_proc(msg.msg); + break; + } +#endif + case CALLBACK_TYPE_ID_NONE: + default: + break; + } + + #if defined(BOARD_BC32RA) || defined(BOARD_BC92RB) || defined(PLAT_SONY_ALT1350)//forrest.liu@20231228 modify for FAE-102027 dump issue + if(msg.callback_type_id != CALLBACK_TYPE_ID_TIMER) + { + if(msg.msg) { + free(msg.msg); + } + } + memset(&msg, 0, sizeof(st_CallBack_Deal)); + #else + if(msg.msg) { + free(msg.msg); + msg.msg = NULL; + } + memset(&msg, 0, sizeof(st_CallBack_Deal)); + #endif + + } + else + { +#if defined(BOARD_BC32RA) || defined(BOARD_BC92RB) || defined(PLAT_SONY_ALT1350)//forrest.liu@20231228 modify for FAE-102027 dump issue + if(msg.callback_type_id != CALLBACK_TYPE_ID_TIMER) + { + if(msg.msg) { + free(msg.msg); + } + } + memset(&msg, 0, sizeof(st_CallBack_Deal)); +#else + if(msg.msg) { + free(msg.msg); + } + memset(&msg, 0, sizeof(st_CallBack_Deal)); +#endif + } + } +} + +#endif + +MP_REGISTER_ROOT_POINTER(void * loadmeth_para); diff --git a/ports/quectel/callbackdeal.h b/ports/quectel/callbackdeal.h new file mode 100644 index 0000000000000..465ca378053c2 --- /dev/null +++ b/ports/quectel/callbackdeal.h @@ -0,0 +1,389 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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. + */ + +// empty file +#ifndef __CALLBACKDEAL_H__ +#define __CALLBACKDEAL_H__ + +#include "py/runtime.h" + +#if MICROPY_QPY_MODULE_BT || MICROPY_QPY_MODULE_BLE +#include "helios_btble.h" +#endif + +#if MICROPY_QPY_MODULE_ALIPAY +#include "helios_aliiot.h" +#endif + +#if MICROPY_QPY_MACHINE_UART +#include "helios_uart.h" +#endif + +#if MICROPY_ENABLE_CALLBACK_DEAL + +typedef struct _c_callback_t { + bool is_method; + mp_obj_t method_self; + qstr method_name; + mp_obj_t cb; + mp_obj_t arg; +}c_callback_t; + +typedef struct{ + uint8_t callback_type_id; + void *msg; +}st_CallBack_Deal; + +enum { + CALLBACK_TYPE_ID_NONE, + CALLBACK_TYPE_ID_LOAD_BOUNDMETH, + CALLBACK_TYPE_ID_EXTINT, + CALLBACK_TYPE_ID_OSTIMER, + CALLBACK_TYPE_ID_HWTIMER, + CALLBACK_TYPE_ID_AUDIO_AUDIO, + CALLBACK_TYPE_ID_AUDIO_RECORD, + CALLBACK_TYPE_ID_AUDIO_TTS, + CALLBACK_TYPE_ID_CAM_CAP, + CALLBACK_TYPE_ID_VOICECALL_RECORD, +#if MICROPY_QPY_MODULE_QUECIOT + CALLBACK_TYPE_ID_QUETCH_CALLCB, +#endif +#if MICROPY_QPY_MODULE_POC + CALLBACK_TYPE_ID_POC, +#endif +#if MICROPY_QPY_MACHINE_KEYPAD + CALLBACK_TYPE_ID_KEYPAD, +#endif +#if MICROPY_QPY_MACHINE_KEY + CALLBACK_TYPE_ID_KEY, +#endif +#if MICROPY_QPY_SENSOR_ICC_KEY + CALLBACK_TYPE_ID_ICCKEY, +#endif +#if MICROPY_QPY_SENSOR_HANDMIC_KEY + CALLBACK_TYPE_ID_HANDMIC_KEY, +#endif +#if MICROPY_QPY_MODULE_EXTUART_WK2114 + CALLBACK_TYPE_ID_WK2114, +#endif +#if MICROPY_QPY_MODULE_GPIO_ENCODER + CALLBACK_TYPE_ID_ENCODER, +#endif +#if MICROPY_QPY_MODULE_EXTGPIO_AW9523 + CALLBACK_TYPE_ID_AW9523, +#endif + CALLBACK_TYPE_ID_TP, +#if MICROPY_QPY_MODULE_BT + CALLBACK_TYPE_ID_BT, +#endif +#if MICROPY_QPY_MODULE_BLE + CALLBACK_TYPE_ID_BLE, +#endif +#if MICROPY_QPY_MODULE_ALIPAY + CALLBACK_TYPE_ID_ALIPAY, +#endif +#if MICROPY_QPY_LPM_WAKEUP + CALLBACK_TYPE_ID_WAKEUP, +#endif +#if MICROPY_QPY_MACHINE_UART + CALLBACK_TYPE_ID_UART, +#endif +#if MICROPY_QPY_MODULE_NET + CALLBACK_TYPE_ID_NET, +#endif +#if MICROPY_QPY_MODULE_DATACALL + CALLBACK_TYPE_ID_DATACALL, +#endif +#if MICROPY_QPY_MODULE_ALIPAY_COLLECTION + CALLBACK_TYPE_ID_ALIPAY_COLLECTION, +#endif +#if MICROPY_QPY_MODULE_SMS + CALLBACK_TYPE_ID_SMS, +#endif +#if MICROPY_QPY_MODULE_JRTC + CALLBACK_TYPE_ID_JRTC, +#endif +#if MICROPY_QPY_MODULE_SIF + CALLBACK_TYPE_ID_SIF, +#endif +#if defined(BOARD_BC32RA) || defined(BOARD_BC92RB) || defined(PLAT_SONY_ALT1350) +#if MICROPY_QPY_MACHINE_TIMER + CALLBACK_TYPE_ID_TIMER, +#endif +#endif +#if defined(BOARD_EC600MCN_LA_POC_XBND) || defined(BOARD_EC600MCN_LE_POC_XBND) || defined(BOARD_EC600MEU_LA_POC_XBND)\ + || defined(BOARD_EC600MLA_LA_POC_XBND) + CALLBACK_TYPE_ID_POCSPEAK, +#endif +#if MICROPY_QPY_MODULE_NFC + CALLBACK_TYPE_ID_NFC, +#endif +#if MICROPY_QPY_SENSOR_VC9202 + CALLBACK_TYPE_ID_VC9202, +#endif +#if MICROPY_QPY_MODULE_LWM2M + CALLBACK_TYPE_ID_LWM2M, +#endif +#if MICROPY_QPY_MODULE_ESIM && MICROPY_QPY_MODULE_ESIM_IPA + CALLBACK_TYPE_ID_ESIM_IPA, +#endif +}; + +typedef struct CallBack_LoadBoundMeth{ + c_callback_t *callback; + void *arg; + struct CallBack_LoadBoundMeth *next; +}st_CallBack_LoadBoundMeth; + +typedef struct{ + uint8_t key_event; + c_callback_t callback; +}st_CallBack_IccKey; + +typedef struct{ + uint8_t gpio_number; + uint8_t key_event; + c_callback_t callback; +}st_CallBack_Key; + +typedef struct{ + uint8_t state; + c_callback_t callback; +}st_CallBack_TP; + +typedef struct{ + uint8_t pin_no; + uint8_t edge; + c_callback_t callback; +}st_CallBack_Extint; + +typedef struct{ + uint8_t key_value; + uint8_t key_state; + c_callback_t callback; +}st_CallBack_Handmic; + +typedef struct{ + uint32_t int_type; + uint32_t port; + uint32_t read_lenth; + c_callback_t callback; +}st_CallBack_Wk2114; + +typedef struct{ + uint8_t pin_no; + uint8_t pin_level; + c_callback_t callback; +}st_CallBack_AW9523; + +typedef struct{ + uint32_t spin_direct; + c_callback_t callback; +}st_CallBack_Encoder; + +enum { + POC_CAL_ELEM_INT, + POC_CAL_ELEM_STR, + POC_CAL_ELEM_UINT64, + POC_CAL_ELEM_ARRAY_INT, + POC_CAL_ELEM_FLOAT, +}; + +typedef struct +{ + int type; + void* data; +}st_CallBack_POC_ELEM; + +typedef struct +{ + st_CallBack_POC_ELEM *para; + int len; + c_callback_t callback; +}st_CallBack_POC; + + +enum {RECORE_TYPE_FILE,RECORE_TYPE_STREAM}; +typedef struct{ + int record_type; + char * p_data; + int len; + int res; + c_callback_t callback; +}st_CallBack_AudioRecord; +typedef struct{ + uint32_t event; + uint32_t errcode; + void *valueT; + uint32_t valLen; + c_callback_t call_cb; +}st_CallBack_Queth; + +typedef struct{ + mp_obj_t fun_in; + size_t n_args; + size_t n_kw; + mp_obj_t *args; +}st_CallBack_lvgl; + +typedef struct{ + uint32_t result; + c_callback_t callback; +}st_CallBack_jrtc; + +typedef struct{ + uint8_t event_id; + uint8_t row; + uint8_t col; + c_callback_t callback; +}st_CallBack_Keypad; + +#if MICROPY_QPY_SENSOR_VC9202 +typedef struct{ + uint32_t work_mode; + uint16_t value; + uint32_t measure_mode; + c_callback_t callback; +}st_CallBack_Sensor_VC9202; +#endif +#if defined(BOARD_BC32RA) || defined(BOARD_BC92RB) || defined(PLAT_SONY_ALT1350) +#if MICROPY_QPY_MACHINE_TIMER +typedef struct{ + c_callback_t callback; +}st_CallBack_Timer; +#endif +#endif + +#if defined(BOARD_EC600MCN_LA_POC_XBND) || defined(BOARD_EC600MCN_LE_POC_XBND) || defined(BOARD_EC600MEU_LA_POC_XBND)\ + || defined(BOARD_EC600MLA_LA_POC_XBND) +typedef struct{ + uint8_t speak_op; + int speak_result; + c_callback_t callback; +}st_CallBack_PocSpeak; +#endif +#if MICROPY_QPY_MACHINE_UART +typedef struct{ + uint64_t ind_type; + Helios_UARTNum port; + uint64_t size; + c_callback_t callback; +}st_CallBack_Uart; +#endif + +#if MICROPY_QPY_MODULE_NFC +typedef struct{ + uint16_t oid; + void* data; + uint8_t data_len; + c_callback_t callback; +}st_CallBack_nfc; +#endif + +#if MICROPY_QPY_MODULE_NET +typedef struct{ + int32_t event_id; + int32_t status; + int32_t act; + int32_t lac; + int32_t cid; + c_callback_t callback; +}st_CallBack_Net; +#endif + +#if MICROPY_QPY_MODULE_DATACALL +typedef struct{ + int32_t profile_idx; + uint8_t sim_id; + int32_t nw_status; + c_callback_t callback; +}st_CallBack_Datacall; +#endif + +#if MICROPY_QPY_MODULE_SMS +typedef struct{ + uint8_t sim_id; + uint8_t index; + char storage[5]; + c_callback_t callback; +}st_CallBack_SMS; +#endif + +#if MICROPY_QPY_MODULE_BT || MICROPY_QPY_MODULE_BLE +typedef struct{ + //void *msg; + Helios_Event event; + c_callback_t callback; +}st_CallBack_BT; +#endif + +#if MICROPY_QPY_MODULE_ALIPAY +typedef struct{ + helios_pay_msg_cmd_t cmd; + helios_pay_rsp_code_t rsp_code; + char *result; + int result_len; + void *userdata; + c_callback_t callback; +}st_CallBack_ALIPAY; +#endif + +#if MICROPY_QPY_MODULE_ALIPAY_COLLECTION +typedef struct{ + int msgID; + int data; + c_callback_t callback; +}st_CallBack_ALIPAY_COLLECTION; +#endif + +#if MICROPY_QPY_LPM_WAKEUP +typedef struct{ + uint8_t level; + c_callback_t callback; +} st_CallBack_Wakeup; +#endif + +#if MICROPY_QPY_MODULE_SIF +typedef struct{ + int data_len; + uint8_t *data; + c_callback_t callback; +} st_CallBack_SIF; +#endif + +bool mp_sched_schedule_callback_register(c_callback_t *callback, mp_obj_t func_obj); +bool mp_sched_schedule_ex(c_callback_t *callback, mp_obj_t arg); + +void qpy_callback_deal_init(void); +void qpy_callback_deal_deinit(void); +int qpy_send_msg_to_callback_deal_thread(uint8_t id, void *msg); +bool qpy_is_callback_deal_thread(void); +st_CallBack_LoadBoundMeth * qpy_callback_para_node_add(c_callback_t *callback, mp_obj_t arg); +void qpy_callback_para_node_delete(st_CallBack_LoadBoundMeth *cb_msg); +void qpy_callback_para_link_free_all(void); +void qpy_callback_para_link_mark_in_used(void); +#endif +#endif //__CALLBACKDEAL_H__ \ No newline at end of file diff --git a/ports/quectel/gccollect.c b/ports/quectel/gccollect.c new file mode 100644 index 0000000000000..e72f2678737d8 --- /dev/null +++ b/ports/quectel/gccollect.c @@ -0,0 +1,120 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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 "mpstate.h" +#include "gc.h" +#include "mpthread.h" +#include "gccollect.h" + +#if defined(PLAT_RDA) +unsigned int ReadSP(void) +{ + uint32_t res; + __asm volatile ( + "move %0, $29\n" + :"=r"(res) + : + : + ); + + return res; +} +#elif defined(PLAT_ECR6600) + +#else +unsigned int ReadSP(void) +{ + uint32_t res; + __asm volatile ( + "mov %0, r13\n" + :"=r"(res) + : + : + ); + + return res; +} +#endif + +void gc_stacktop_set(void * ptr) +{ + MP_STATE_PORT(global_stacktop_ptr) = ptr; +} + +void gc_collect(void) { + // get current time, in case we want to time the GC + #if 0 + uint32_t start = mp_hal_ticks_us(); + #endif +#if defined(PLAT_ECR6600) + int val = 0; +#endif + // start the GC + gc_collect_start(); +#if defined(PLAT_ECR6600) + uintptr_t sp = (uintptr_t)&val; +#else + // get the registers and the sp + uintptr_t sp = (uintptr_t)ReadSP(); +#endif + if(mp_is_python_thread()) + { + // trace the stack, including the registers (since they live on the stack in this function) + gc_collect_root((void **)sp, ((uint32_t)MP_STATE_THREAD(stack_top) - sp) / sizeof(uint32_t)); + } + else if(NULL != MP_STATE_PORT(global_stacktop_ptr)) + { + gc_collect_root((void **)sp, ((uint32_t)MP_STATE_PORT(global_stacktop_ptr) - sp) / sizeof(uint32_t)); + } + else + { + //do nothing + } + + // trace root pointers from any threads + #if MICROPY_PY_THREAD + mp_thread_gc_others(); + #endif + + // end the GC + gc_collect_end(); + + #if 0 + // print GC info + uint32_t ticks = mp_hal_ticks_us() - start; + gc_info_t info; + gc_info(&info); + printf("GC@%lu %lums\n", start, ticks); + printf(" " UINT_FMT " total\n", info.total); + printf(" " UINT_FMT " : " UINT_FMT "\n", info.used, info.free); + printf(" 1=" UINT_FMT " 2=" UINT_FMT " m=" UINT_FMT "\n", info.num_1block, info.num_2block, info.max_block); + #endif +} + +MP_REGISTER_ROOT_POINTER(volatile void * global_stacktop_ptr); diff --git a/ports/quectel/gccollect.h b/ports/quectel/gccollect.h new file mode 100644 index 0000000000000..9ce6896e47df7 --- /dev/null +++ b/ports/quectel/gccollect.h @@ -0,0 +1,41 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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_QUECTEL_GCCOLLECT_H__ +#define __MICROPY_INCLUDED_QUECTEL_GCCOLLECT_H__ + +void gc_stacktop_set(void * ptr); +void gc_collect(void); + +//Set a stack address as the end address of the GC collection +//Do not add {} to the macro definition to prevent the scoping of stack_dummy from changing +#define GC_STACKTOP_SET() int stack_dummy;gc_stacktop_set(&stack_dummy); + +//Clears the gc collection end stack pointer for global non-Python threads +#define GC_STACKTOP_CLEAR() gc_stacktop_set(NULL); + +#endif + diff --git a/ports/quectel/help.c b/ports/quectel/help.c new file mode 100644 index 0000000000000..fadb2f60e5195 --- /dev/null +++ b/ports/quectel/help.c @@ -0,0 +1,44 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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/builtin.h" + +const char quecpython_help_text[] = + "Welcome to QuecPython! The Quecpython is a \n" + "small microcontroller that runs MicroPython.\n" + "\n" + "For online help please visit https://python.quectel.com/wiki \n" + "\n" + "Control commands:\n" + " CTRL-A -- on a blank line, enter raw REPL mode\n" + " CTRL-B -- on a blank line, enter normal REPL mode\n" + " CTRL-C -- interrupt a running program\n" + " CTRL-D -- on a blank line, do a soft reset of the board\n" + " CTRL-E -- on a blank line, enter paste mode\n" + "\n" + "For further help on a specific object, type help(obj)\n" + "For a list of available modules, type help('modules')\n" +; diff --git a/ports/quectel/machine_extint.c b/ports/quectel/machine_extint.c new file mode 100644 index 0000000000000..6eabf508f6889 --- /dev/null +++ b/ports/quectel/machine_extint.c @@ -0,0 +1,734 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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 + +#include "runtime.h" +#include "gc.h" +#include "mphal.h" +#include "gccollect.h" + +#if MICROPY_QPY_MACHINE_EXTINT +#include "helios_pin.h" +#include "helios_extint.h" +#include "helios_debug.h" +#include "callbackdeal.h" +#include "helios_os.h" + +//#if defined(PLAT_EIGEN) +static Helios_Thread_t thread_id = 0; +static Helios_MsgQ_t extint_queue = 0; +typedef struct +{ + uint8_t msg_type; + uint8_t pin; + uint8_t edge; + void* cb; +}extint_Msg; + +//#endif +#if 1 +#define EXTINT_LOG(msg, ...) custom_log("extint", msg, ##__VA_ARGS__) +#else +#define EXTINT_LOG(msg, ...) +#endif +/* sample time (ms) */ +#define EXTINT_SAMPLE_TIME (10) + +extern int Helios_GPIO_GetLevel(Helios_GPIONum gpio_num); +const mp_obj_type_t machine_extint_type; + +#if defined(BOARD_EG810MCN_GA_ALIPAY) || defined(BOARD_EG810MCN_GA_VOLTE) +static int __fastIntGpio = 0xffff; +#endif + +typedef struct { + mp_obj_base_t base; + mp_int_t line; + mp_int_t mode; + mp_int_t pull; + mp_int_t fliter_time; + c_callback_t callback; +} extint_obj_t; + + +typedef struct { + mp_int_t rising_count; + mp_int_t falling_count; +} extint_count_t; + +#if defined(PLAT_aic8800m40) +typedef void(*eint_handler_t)(int EDGE); +#else +typedef void(*eint_handler_t)(void); + +#endif + +static extint_obj_t *extint_obj[HELIOS_GPIOMAX]; +static extint_count_t extint_count[HELIOS_GPIOMAX] = {0}; +static Helios_OSTimer_t extint_fliter_timer[HELIOS_GPIOMAX] = {0}; +static uint8_t extint_fliter_timer_is_start[HELIOS_GPIOMAX] = {0}; + +enum { + HELIOS_EXTINT_RISING, + HELIOS_EXTINT_FALLING, +}; + +#define EINT_HANDLER_DEF(n) handler##n +#define PLAT_EINT_HANDLER_DEF(n) BOOST_PP_REPEAT_1(n,EINT_HANDLER_DEF) + +/* +** Jayceon-20200908: +** Replace function mp_call_function_1_protected() with mp_sched_schedule_ex to slove the dump problem. +*/ +#if MICROPY_ENABLE_CALLBACK_DEAL +#define EXTINT_CALLBACK_OP(X, edge) do{ \ + st_CallBack_Extint *extint = malloc(sizeof(st_CallBack_Extint)); \ + if(NULL != extint) { \ + extint->pin_no = X; \ + extint->edge = edge; \ + extint->callback = extint_obj[X]->callback; \ + if(qpy_send_msg_to_callback_deal_thread(CALLBACK_TYPE_ID_EXTINT, extint)) \ + { \ + free(extint); \ + } \ + } \ + }while(0) +#else +#define EXTINT_CALLBACK_OP(X, edge) do{ \ + GC_STACKTOP_SET(); \ + mp_obj_t extint_list[2] = { \ + mp_obj_new_int(X), \ + mp_obj_new_int(edge), \ + }; \ + mp_sched_schedule(&extint_obj[X]->callback, mp_obj_new_list(2, extint_list)); \ + GC_STACKTOP_CLEAR(); \ + }while(0) + +#endif + + +#if defined(PLAT_aic8800m40) +#define HANDLER_FUN(X) \ +static void fliter_timer_handler##X(void *args) { \ + int edge = (int)args; \ + static uint32_t extint_fliter_count = 0; \ + uint32_t extint_fliter_count_max = extint_obj[X]->fliter_time / EXTINT_SAMPLE_TIME; \ + int level = Helios_GPIO_GetLevel(X); \ + switch (edge) { \ + case HELIOS_EXTINT_RISING: \ + if (level != 1) { \ + extint_fliter_count = 0; \ + } \ + break; \ + case HELIOS_EXTINT_FALLING: \ + if (level != 0) { \ + extint_fliter_count = 0; \ + } \ + break; \ + } \ + if (++extint_fliter_count > extint_fliter_count_max) { \ + Helios_OSTimer_Stop(extint_fliter_timer[X]); \ + extint_fliter_count = 0; \ + extint_fliter_timer_is_start[X] = false; \ + EXTINT_CALLBACK_OP(X, edge); \ + } \ +} \ +static void handler##X(int EDGE) \ +{ \ + int edge = EDGE; \ + if (extint_obj[X]->callback.cb != mp_const_none && \ + ((mp_sched_num_pending() < MICROPY_SCHEDULER_DEPTH))) \ + { \ + if (extint_obj[X]->fliter_time > 0 && !extint_fliter_timer_is_start[X]) { \ + if (!extint_fliter_timer[X]) { \ + extint_fliter_timer[X] = Helios_OSTimer_Create(); \ + if (!extint_fliter_timer[X]) { \ + EXTINT_LOG("error: extint fliter timer create failed!"); \ + EXTINT_CALLBACK_OP(X, edge); \ + } \ + } else { \ + Helios_OSTimerAttr attr = { \ + .ms = EXTINT_SAMPLE_TIME, \ + .cycle_enable = 1, \ + .cb = fliter_timer_handler##X, \ + .argv = (void*)edge \ + }; \ + Helios_OSTimer_Start(extint_fliter_timer[X], &attr); \ + extint_fliter_timer_is_start[X] = true; \ + } \ + } else if(extint_obj[X]->fliter_time == 0){ \ + EXTINT_CALLBACK_OP(X, edge); \ + } \ + } \ + Helios_ExtInt_Enable(extint_obj[X]->line); \ +} +#else +#define HANDLER_FUN(X) \ +static void fliter_timer_handler##X(void *args) { \ + int edge = (int)args; \ + static uint32_t extint_fliter_count = 0; \ + uint32_t extint_fliter_count_max = extint_obj[X]->fliter_time / EXTINT_SAMPLE_TIME; \ + int level = Helios_GPIO_GetLevel(X); \ + switch (edge) { \ + case HELIOS_EXTINT_RISING: \ + if (level != 1) { \ + Helios_OSTimer_Stop(extint_fliter_timer[X]); \ + extint_fliter_count = 0; \ + extint_fliter_timer_is_start[X] = false;\ + } \ + break; \ + case HELIOS_EXTINT_FALLING: \ + if (level != 0) { \ + Helios_OSTimer_Stop(extint_fliter_timer[X]); \ + extint_fliter_count = 0; \ + extint_fliter_timer_is_start[X] = false;\ + } \ + break; \ + } \ + if (++extint_fliter_count > extint_fliter_count_max) { \ + Helios_OSTimer_Stop(extint_fliter_timer[X]); \ + extint_fliter_count = 0; \ + extint_fliter_timer_is_start[X] = false; \ + EXTINT_CALLBACK_OP(X, edge); \ + if(edge == HELIOS_EXTINT_RISING) \ + { \ + extint_count[X].rising_count++; \ + } \ + else \ + { \ + extint_count[X].falling_count++; \ + } \ + } \ + Helios_ExtInt_Enable(extint_obj[X]->line); \ +} \ +static void handler##X(void) \ +{ \ + int edge = HELIOS_EXTINT_RISING;\ + if(extint_obj[X]->mode == HELIOS_EDGE_RISING) \ + { \ + if(extint_obj[X]->fliter_time == 0) \ + { \ + extint_count[X].rising_count++; \ + } \ + } \ + else if(extint_obj[X]->mode == HELIOS_EDGE_FALLING) \ + { \ + edge = HELIOS_EXTINT_FALLING; \ + if(extint_obj[X]->fliter_time == 0) \ + { \ + extint_count[X].falling_count++; \ + } \ + } \ + else \ + { \ + if(Helios_GPIO_GetLevel((Helios_GPIONum)X) == 0) \ + { \ + edge = HELIOS_EXTINT_FALLING; \ + if(extint_obj[X]->fliter_time == 0) \ + { \ + extint_count[X].falling_count++; \ + } \ + } \ + else \ + { \ + if(extint_obj[X]->fliter_time == 0) \ + { \ + extint_count[X].rising_count++; \ + } \ + } \ + } \ + if (extint_obj[X]->callback.cb != mp_const_none && \ + ((mp_sched_num_pending() < MICROPY_SCHEDULER_DEPTH))) \ + { \ + if (extint_obj[X]->fliter_time > 0 && !extint_fliter_timer_is_start[X]) { \ + extint_fliter_timer_is_start[X] = true;\ + if(extint_queue && thread_id) \ + { \ + extint_Msg msg; \ + msg.msg_type = 1;\ + msg.pin = X; \ + msg.edge = edge; \ + msg.cb = fliter_timer_handler##X;\ + Helios_MsgQ_Put(extint_queue, (void *)&msg, sizeof(extint_Msg), HELIOS_NO_WAIT);\ + } \ + else\ + {\ + Helios_OSTimerAttr attr = \ + { \ + .ms = EXTINT_SAMPLE_TIME,\ + .cycle_enable = 1, \ + .cb = fliter_timer_handler##X, \ + .argv = (void*)edge \ + }; \ + if(extint_fliter_timer[X])\ + {\ + Helios_OSTimer_Start(extint_fliter_timer[X], &attr); \ + }\ + }\ + } else if(extint_obj[X]->fliter_time == 0){\ + if(extint_queue && thread_id) \ + { \ + extint_Msg msg; \ + msg.msg_type = 0;\ + msg.pin = X; \ + msg.edge = edge; \ + Helios_MsgQ_Put(extint_queue, (void *)&msg, sizeof(extint_Msg), HELIOS_NO_WAIT);\ + } \ + else \ + { \ + EXTINT_CALLBACK_OP(X, edge); \ + } \ + } \ + } \ + if((extint_obj[X]->fliter_time == 0) && !(extint_queue && thread_id)) \ + { \ + Helios_ExtInt_Enable(extint_obj[X]->line); \ + } \ +} +#endif + + +HANDLER_FUN_0_N(PLAT_GPIO_NUM) + + + + +eint_handler_t eint_handler[HELIOS_GPIOMAX] = { + handler0, PLAT_EINT_HANDLER_DEF(PLAT_GPIO_NUM) +}; + + + +static void extint_count_reset(int offset) { + extint_count[offset].falling_count = 0; + extint_count[offset].rising_count = 0; +} + +/// \method line() +/// Return the line number that the pin is mapped to. +static mp_obj_t extint_obj_line(mp_obj_t self_in) { + extint_obj_t *self = MP_OBJ_TO_PTR(self_in); + return MP_OBJ_NEW_SMALL_INT(self->line); +} +static MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_line_obj, extint_obj_line); + +/// \method enable() +/// Enable a disabled interrupt. +static mp_obj_t extint_obj_enable(mp_obj_t self_in) { + extint_obj_t *self = MP_OBJ_TO_PTR(self_in); + int ret = Helios_ExtInt_Enable((Helios_GPIONum) self->line); + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_enable_obj, extint_obj_enable); + +/// \method disable() +/// Disable the interrupt associated with the ExtInt object. +/// This could be useful for debouncing. +static mp_obj_t extint_obj_disable(mp_obj_t self_in) { + extint_obj_t *self = MP_OBJ_TO_PTR(self_in); + int ret = Helios_ExtInt_Disable((Helios_GPIONum) self->line); + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_disable_obj, extint_obj_disable); + +#if defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) || defined(PLAT_SONY_ALT1350) +static void extint_entry(void * argv) +{ + extint_Msg msg; + int edge; + while(1) + { + Helios_MsgQ_Get(extint_queue, (void *)&msg, sizeof(extint_Msg), HELIOS_WAIT_FOREVER); + edge = msg.edge; + if(msg.msg_type == 1)//start timer + { + if(extint_fliter_timer[msg.pin]) + { + Helios_OSTimerAttr attr = + { + .ms = EXTINT_SAMPLE_TIME, + .cycle_enable = 1, + .cb = (void(*)(void *))msg.cb, + .argv = (void*)edge + }; + if(Helios_OSTimer_Start(extint_fliter_timer[msg.pin], &attr))//eigen 618 plat,we cant call Helios_OSTimer_Start in IRQ + { + } + else + { + } + } + } + else + { + EXTINT_CALLBACK_OP(msg.pin,edge); + Helios_ExtInt_Enable(msg.pin); + } + } +} +#endif +/// \classmethod \constructor(pin, mode, pull, callback) +/// Create an ExtInt object: +/// +/// - `pin` is the pin on which to enable the interrupt (can be a pin object or any valid pin name). +/// - `mode` can be one of: +/// - `ExtInt.IRQ_RISING` - trigger on a rising edge; +/// - `ExtInt.IRQ_FALLING` - trigger on a falling edge; +/// - `ExtInt.IRQ_RISING_FALLING` - trigger on a rising or falling edge. +/// - `pull` can be one of: +/// - `pyb.Pin.PULL_NONE` - no pull up or down resistors; +/// - `pyb.Pin.PULL_UP` - enable the pull-up resistor; +/// - `pyb.Pin.PULL_DOWN` - enable the pull-down resistor. +/// - `callback` is the function to call when the interrupt triggers. The +/// callback function must accept exactly 1 argument, which is the line that +/// triggered the interrupt. +static const mp_arg_t pyb_extint_make_new_args[] = { + { MP_QSTR_pin, MP_ARG_REQUIRED | MP_ARG_INT, {.u_obj = 0} }, + { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_pull, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_callback, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, +#if defined(BOARD_EG810MCN_GA_ALIPAY) || defined(BOARD_EG810MCN_GA_VOLTE) + { MP_QSTR_fast, MP_ARG_INT, {.u_int = 0} }, +#endif + { MP_QSTR_filter_time, MP_ARG_INT, {.u_int = 0} }, +}; +#define PYB_EXTINT_MAKE_NEW_NUM_ARGS MP_ARRAY_SIZE(pyb_extint_make_new_args) + +static mp_obj_t extint_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + // type_in == extint_obj_type + // parse args + mp_arg_val_t vals[PYB_EXTINT_MAKE_NEW_NUM_ARGS]; + mp_arg_parse_all_kw_array(n_args, n_kw, args, PYB_EXTINT_MAKE_NEW_NUM_ARGS, pyb_extint_make_new_args, vals); + +#if !defined(PLAT_ECR6600) + if (vals[0].u_int < HELIOS_GPIO0 || vals[0].u_int > HELIOS_GPIOMAX) { + mp_raise_ValueError(MP_ERROR_TEXT("invalid pin value")); + } +#endif + + if (extint_obj[vals[0].u_int] == NULL) + { + extint_obj[vals[0].u_int] = mp_obj_malloc_with_finaliser(extint_obj_t, &machine_extint_type); + } + extint_obj_t *self = extint_obj[vals[0].u_int]; + self->base.type = type; + self->line = vals[0].u_int; + + self->mode = vals[1].u_int; + if (self->mode < HELIOS_EDGE_RISING || self->mode > HELIOS_EDGE_BOTH) { + mp_raise_ValueError(MP_ERROR_TEXT("invalid mode value")); + } + + self->pull = vals[2].u_int; + if (self->pull < HELIOS_PULL_NONE || self->pull > HELIOS_PULL_DOWN) { + mp_raise_ValueError(MP_ERROR_TEXT("invalid pull value")); + } + + static c_callback_t cb = {0}; + memset(&cb, 0, sizeof(c_callback_t)); + cb.arg = mp_obj_new_tuple(2, NULL); + self->callback = cb; + mp_sched_schedule_callback_register(&self->callback, vals[3].u_obj); + // EXTINT_LOG("ds cb 457!\n"); + + Helios_ExtIntStruct extint_struct = {0}; + extint_struct.gpio_trigger = HELIOS_EDGE_TRIGGER; + extint_struct.gpio_edge = self->mode; + extint_struct.gpio_debounce = HELIOS_DEBOUNCE_EN; + extint_struct.gpio_pull = self->pull; + extint_struct.eint_cb = NULL; + extint_struct.wakeup_eint_cb = eint_handler[self->line]; + + // EXTINT_LOG("%x\n", extint_struct.wakeup_eint_cb); + + Helios_ExtInt_Deinit((Helios_GPIONum) self->line); + + if(0 != Helios_ExtInt_Init((Helios_GPIONum) self->line, &extint_struct)) { + mp_raise_ValueError(MP_ERROR_TEXT("Interrupt initialization failed")); + } + +#if defined(BOARD_EG810MCN_GA_ALIPAY) || defined(BOARD_EG810MCN_GA_VOLTE) + if(vals[4].u_int == 1) { + __fastIntGpio = self->line; + Helios_ExtInt_FastSetGpio(__fastIntGpio); + } else { + if(__fastIntGpio == self->line) { + __fastIntGpio = 0xffff; + Helios_ExtInt_FastSetGpio(__fastIntGpio); + } + } + self->fliter_time = vals[5].u_int; +#else + self->fliter_time = vals[4].u_int; +#endif + + if (self->fliter_time < 0) + { + mp_raise_ValueError(MP_ERROR_TEXT("invalid fliter time value")); + } + + if(self->fliter_time > 0) + { + if(!extint_fliter_timer[self->line]) + { + extint_fliter_timer[self->line] = Helios_OSTimer_Create(); + if (!extint_fliter_timer[self->line]) + { + mp_raise_ValueError(MP_ERROR_TEXT("error: extint fliter timer create failed!")); + } + } + } +#if defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) || defined(PLAT_SONY_ALT1350) + + if(extint_queue == 0) + { + extint_queue = Helios_MsgQ_Create(256, sizeof(extint_Msg)); + if(extint_queue == 0) + { + mp_raise_ValueError(MP_ERROR_TEXT("initialization failed")); + } + } + + if(thread_id == 0) + { + Helios_ThreadAttr ThreadAttr = + { + .name = "machine_extint", + .stack_size = 2048, + .priority = 92, + .entry = extint_entry, + .argv = NULL + }; + thread_id = Helios_Thread_Create(&ThreadAttr); + if(thread_id == 0) + { + mp_raise_ValueError(MP_ERROR_TEXT("initialization failed")); + } + } + +#endif + extint_count_reset(self->line); + return MP_OBJ_FROM_PTR(self); +} + +static void extint_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + extint_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_printf(print, "", self->line); +} + +static mp_obj_t extint_obj_read_count(mp_obj_t self_in, mp_obj_t is_reset) { + extint_obj_t *self = MP_OBJ_TO_PTR(self_in); + int reset_flag = mp_obj_get_int(is_reset); + + if(reset_flag != 0 && reset_flag != 1) { + mp_raise_ValueError(MP_ERROR_TEXT("invalid is_reset value, must in [0,1]")); + } + +#if defined(BOARD_EG810MCN_GA_ALIPAY) || defined(BOARD_EG810MCN_GA_VOLTE) + int count = 0; + if(__fastIntGpio == self->line) { + count += Helios_ExtInt_FastGetCnt(); + if(extint_obj[self->line]->mode == HELIOS_EDGE_RISING){ + extint_count[self->line].rising_count += count; + } else if(extint_obj[self->line]->mode == HELIOS_EDGE_FALLING) { + extint_count[self->line].falling_count += count; + } else { + if(count % 2 == 0) { + extint_count[self->line].rising_count += count / 2; + extint_count[self->line].falling_count += count / 2; + } else { + if(Helios_GPIO_GetLevel(self->line) == 0) { + extint_count[self->line].rising_count++; + } else { + extint_count[self->line].falling_count++; + } + } + } + } +#endif + + mp_obj_t extint_list[2] = { + mp_obj_new_int(extint_count[self->line].rising_count), + mp_obj_new_int(extint_count[self->line].falling_count), + }; + + if(1 == reset_flag) { + extint_count_reset(self->line); + } + return mp_obj_new_list(2, extint_list); +} +static MP_DEFINE_CONST_FUN_OBJ_2(extint_obj_read_count_obj, extint_obj_read_count); + +static mp_obj_t extint_obj_count_reset(mp_obj_t self_in) { + extint_obj_t *self = MP_OBJ_TO_PTR(self_in); + extint_count_reset(self->line); + + return mp_obj_new_int(0); + +} +static MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_count_reset_obj, extint_obj_count_reset); + +static mp_obj_t extint_obj_Deinit(mp_obj_t self_in) { + extint_obj_t *self = MP_OBJ_TO_PTR(self_in); + int ret = -1; + //EXTINT_LOG("extint deinit"); + + extint_obj[self->line] = NULL; + extint_count_reset(self->line); + + if((0 == Helios_ExtInt_Disable((Helios_GPIONum) self->line)) && (0 == Helios_ExtInt_Deinit((Helios_GPIONum) self->line))) { + ret = 0; + } + + return mp_obj_new_int(ret); + +} +static MP_DEFINE_CONST_FUN_OBJ_1(extint__del__obj, extint_obj_Deinit); + +static mp_obj_t extint_obj_read_level(mp_obj_t self_in) { + extint_obj_t *self = MP_OBJ_TO_PTR(self_in); + int ret = -1; + + ret = Helios_GPIO_GetLevel((Helios_GPIONum) self->line); + + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_read_level_obj, extint_obj_read_level); + + +static const mp_rom_map_elem_t extint_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&extint__del__obj) }, + { MP_ROM_QSTR(MP_QSTR_line), MP_ROM_PTR(&extint_obj_line_obj) }, + { MP_ROM_QSTR(MP_QSTR_enable), MP_ROM_PTR(&extint_obj_enable_obj) }, + { MP_ROM_QSTR(MP_QSTR_disable), MP_ROM_PTR(&extint_obj_disable_obj) }, + { MP_ROM_QSTR(MP_QSTR_read_count), MP_ROM_PTR(&extint_obj_read_count_obj) }, + { MP_ROM_QSTR(MP_QSTR_count_reset), MP_ROM_PTR(&extint_obj_count_reset_obj) }, + { MP_ROM_QSTR(MP_QSTR_read_level), MP_ROM_PTR(&extint_obj_read_level_obj)}, + + // class constants + /// \constant IRQ_RISING - interrupt on a rising edge + /// \constant IRQ_FALLING - interrupt on a falling edge + /// \constant IRQ_RISING_FALLING - interrupt on a rising or falling edge + { MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(HELIOS_EDGE_RISING) }, + { MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(HELIOS_EDGE_FALLING) }, + { MP_ROM_QSTR(MP_QSTR_IRQ_RISING_FALLING), MP_ROM_INT(HELIOS_EDGE_BOTH) }, + { MP_ROM_QSTR(MP_QSTR_PULL_DISABLE), MP_ROM_INT(HELIOS_PULL_NONE) }, + { MP_ROM_QSTR(MP_QSTR_PULL_PU), MP_ROM_INT(HELIOS_PULL_UP) }, + { MP_ROM_QSTR(MP_QSTR_PULL_PD), MP_ROM_INT(HELIOS_PULL_DOWN) }, + { MP_ROM_QSTR(MP_QSTR_GPIO0), MP_ROM_INT(HELIOS_GPIO0) }, +#if defined(PLAT_Qualcomm) +#if defined(BOARD_BG95M1) || defined(BOARD_BG95M2) || defined(BOARD_BG95M3) \ + || defined(BOARD_BG95M8) || defined(BOARD_BG95M9) || defined(BOARD_BG95M3_LX) \ + || defined(BOARD_BG95M6) || defined(BOARD_BG95M8_SANX) + { MP_ROM_QSTR(MP_QSTR_GPIO2), MP_ROM_INT(HELIOS_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_GPIO3), MP_ROM_INT(HELIOS_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_GPIO6), MP_ROM_INT(HELIOS_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_GPIO7), MP_ROM_INT(HELIOS_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_GPIO8), MP_ROM_INT(HELIOS_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_GPIO9), MP_ROM_INT(HELIOS_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_GPIO11), MP_ROM_INT(HELIOS_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_GPIO12), MP_ROM_INT(HELIOS_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_GPIO14), MP_ROM_INT(HELIOS_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_GPIO16), MP_ROM_INT(HELIOS_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_GPIO17), MP_ROM_INT(HELIOS_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_GPIO18), MP_ROM_INT(HELIOS_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_GPIO19), MP_ROM_INT(HELIOS_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_GPIO20), MP_ROM_INT(HELIOS_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_GPIO21), MP_ROM_INT(HELIOS_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_GPIO22), MP_ROM_INT(HELIOS_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_GPIO23), MP_ROM_INT(HELIOS_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_GPIO24), MP_ROM_INT(HELIOS_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_GPIO25), MP_ROM_INT(HELIOS_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_GPIO26), MP_ROM_INT(HELIOS_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_GPIO29), MP_ROM_INT(HELIOS_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_GPIO30), MP_ROM_INT(HELIOS_GPIO30) }, +#elif defined(BOARD_BG77) + { MP_ROM_QSTR(MP_QSTR_GPIO1), MP_ROM_INT(HELIOS_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_GPIO2), MP_ROM_INT(HELIOS_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_GPIO4), MP_ROM_INT(HELIOS_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_GPIO5), MP_ROM_INT(HELIOS_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_GPIO8), MP_ROM_INT(HELIOS_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_GPIO10), MP_ROM_INT(HELIOS_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_GPIO13), MP_ROM_INT(HELIOS_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_GPIO14), MP_ROM_INT(HELIOS_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_GPIO17), MP_ROM_INT(HELIOS_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_GPIO20), MP_ROM_INT(HELIOS_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_GPIO21), MP_ROM_INT(HELIOS_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_GPIO22), MP_ROM_INT(HELIOS_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_GPIO25), MP_ROM_INT(HELIOS_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_GPIO28), MP_ROM_INT(HELIOS_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GPIO31), MP_ROM_INT(HELIOS_GPIO31) }, + { MP_ROM_QSTR(MP_QSTR_GPIO33), MP_ROM_INT(HELIOS_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_GPIO34), MP_ROM_INT(HELIOS_GPIO34) }, + + { MP_ROM_QSTR(MP_QSTR_GPIO35), MP_ROM_INT(HELIOS_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_GPIO36), MP_ROM_INT(HELIOS_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_GPIO39), MP_ROM_INT(HELIOS_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_GPIO40), MP_ROM_INT(HELIOS_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_GPIO42), MP_ROM_INT(HELIOS_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_GPIO43), MP_ROM_INT(HELIOS_GPIO43) }, +#elif defined(BOARD_BG600LM3) + { MP_ROM_QSTR(MP_QSTR_GPIO1), MP_ROM_INT(HELIOS_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_GPIO2), MP_ROM_INT(HELIOS_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_GPIO3), MP_ROM_INT(HELIOS_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_GPIO6), MP_ROM_INT(HELIOS_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_GPIO7), MP_ROM_INT(HELIOS_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_GPIO8), MP_ROM_INT(HELIOS_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_GPIO10), MP_ROM_INT(HELIOS_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_GPIO11), MP_ROM_INT(HELIOS_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_GPIO15), MP_ROM_INT(HELIOS_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_GPIO16), MP_ROM_INT(HELIOS_GPIO16) }, + + { MP_ROM_QSTR(MP_QSTR_GPIO17), MP_ROM_INT(HELIOS_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_GPIO18), MP_ROM_INT(HELIOS_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_GPIO19), MP_ROM_INT(HELIOS_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_GPIO20), MP_ROM_INT(HELIOS_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_GPIO23), MP_ROM_INT(HELIOS_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_GPIO25), MP_ROM_INT(HELIOS_GPIO25) }, +#endif +#else +#if !defined(PLAT_ECR6600) + PLAT_GPIO_DEF(PLAT_GPIO_NUM), +#endif +#endif +}; + +static MP_DEFINE_CONST_DICT(extint_locals_dict, extint_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + machine_extint_type, + MP_QSTR_ExtInt, + MP_TYPE_FLAG_NONE, + make_new, extint_make_new, + print, extint_obj_print, + locals_dict, &extint_locals_dict + ); +#endif diff --git a/ports/quectel/machine_hw_spi.c b/ports/quectel/machine_hw_spi.c new file mode 100644 index 0000000000000..6a6c79460ae5b --- /dev/null +++ b/ports/quectel/machine_hw_spi.c @@ -0,0 +1,265 @@ +/* + * Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. + * + * 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. + */ + +#include +#include +#include + +#include "py/runtime.h" +#include "py/gc.h" +#include "py/mphal.h" +#include "py/mperrno.h" +#include "mphalport.h" + +#if MICROPY_QPY_MACHINE_SPI + +#include "helios_spi.h" +#include "helios_debug.h" + + +#define HELIOS_SPI_LOG(msg, ...) custom_log("machine spi", msg, ##__VA_ARGS__) + + +const mp_obj_type_t machine_hard_spi_type; + +typedef struct _machine_hard_spi_obj_t { + mp_obj_base_t base; + uint32_t port; + uint32_t mode; + uint32_t clk; +} machine_hard_spi_obj_t; + +static void machine_hard_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + machine_hard_spi_obj_t *self = self_in; + mp_printf(print, "spi%d", self->port); +} + +mp_obj_t machine_hard_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_port, ARG_mode, ARG_clk }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_port, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_clk, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + uint32_t port = args[ARG_port].u_int; + uint32_t mode = args[ARG_mode].u_int; + uint32_t clk = args[ARG_clk].u_int; + int ret=0; + + if (port > HELIOS_SPI3) { + mp_raise_ValueError(MP_ERROR_TEXT("port must be (0~3)")); + } + + if ( mode > 3) { + mp_raise_ValueError(MP_ERROR_TEXT("mode must be (0~3)")); + } + +#if defined(PLAT_Unisoc) + if (clk > 9) { + mp_raise_ValueError(MP_ERROR_TEXT("clk must be (0~9)")); + } +#elif defined(PLAT_RDA) + if (clk > 39) { + mp_raise_ValueError(MP_ERROR_TEXT("clk must be (0~39)")); + } +#elif defined(PLAT_Unisoc_8850) +if (clk > 14) +{ + mp_raise_ValueError(MP_ERROR_TEXT("clk must be (0~14)")); +} +#elif defined(PLAT_SONY_ALT1350) +if (clk > 30) +{ + mp_raise_ValueError(MP_ERROR_TEXT("clk must be (0~30)")); +} +#else + if (clk > 6) { + mp_raise_ValueError(MP_ERROR_TEXT("clk must be (0~6)")); + } +#endif + + + machine_hard_spi_obj_t *self = m_new_obj(machine_hard_spi_obj_t); + + self->base.type = &machine_hard_spi_type; + self->port = port; + self->mode = mode; + self->clk = clk; + + ret = Helios_SPI_Init((Helios_SPINum) self->port, (Helios_SPIMode) self->mode, (uint32_t) self->clk); + if(ret != 0) { + mp_raise_ValueError(MP_ERROR_TEXT("spi init fail")); + } + + HELIOS_SPI_LOG("Helios_SPI_Init %d\r\n",ret); + return MP_OBJ_FROM_PTR(self); +} + +static const mp_arg_t machine_spi_mem_allowed_args[] = { + { MP_QSTR_databuf, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_datasize, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, +}; +static mp_obj_t machine_spi_write_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_databuf, ARG_datasize }; + mp_arg_val_t args[MP_ARRAY_SIZE(machine_spi_mem_allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, + MP_ARRAY_SIZE(machine_spi_mem_allowed_args), machine_spi_mem_allowed_args, args); + + machine_hard_spi_obj_t *self = (machine_hard_spi_obj_t *)MP_OBJ_TO_PTR(pos_args[0]); + + // get the buffer to write the data from + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[ARG_databuf].u_obj, &bufinfo, MP_BUFFER_READ); + + int length = (size_t)args[ARG_datasize].u_int > bufinfo.len ? bufinfo.len : (size_t)args[ARG_datasize].u_int; + // do the transfer + + int ret = Helios_SPI_Write((Helios_SPINum) self->port, (void*) bufinfo.buf, (size_t) length); + if (ret < 0) { + HELIOS_SPI_LOG("Helios_SPI_Write ret=%d\r\n",ret); + mp_raise_OSError(-ret); + } + + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_KW(machine_spi_write_obj, 1, machine_spi_write_mem); + +static mp_obj_t machine_spi_read_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_databuf, ARG_datasize }; + mp_arg_val_t args[MP_ARRAY_SIZE(machine_spi_mem_allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, + MP_ARRAY_SIZE(machine_spi_mem_allowed_args), machine_spi_mem_allowed_args, args); + + machine_hard_spi_obj_t *self = (machine_hard_spi_obj_t *)MP_OBJ_TO_PTR(pos_args[0]); + + // get the buffer to read the data into + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[ARG_databuf].u_obj, &bufinfo, MP_BUFFER_WRITE); + + int length = (size_t)args[ARG_datasize].u_int > bufinfo.len ? bufinfo.len : (size_t)args[ARG_datasize].u_int; + + // do the transfer + int ret = Helios_SPI_Read((Helios_SPINum) self->port, (void*) bufinfo.buf, (size_t) length); + if (ret < 0) { + HELIOS_SPI_LOG("spi read ret=%d\r\n",ret); + mp_raise_OSError(-ret); + } + + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_KW(machine_spi_read_obj, 1, machine_spi_read_mem); +#ifndef PLAT_SONY_ALT1350 +static const mp_arg_t machine_spi_write_read_mem_allowed_args[] = { + { MP_QSTR_readbuf, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_writebuf, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_datasize, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, +}; +static mp_obj_t machine_spi_write_read_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_readbuf, ARG_writebuf, ARG_datasize }; + mp_arg_val_t args[MP_ARRAY_SIZE(machine_spi_write_read_mem_allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, + MP_ARRAY_SIZE(machine_spi_write_read_mem_allowed_args), machine_spi_write_read_mem_allowed_args, args); + + machine_hard_spi_obj_t *self = (machine_hard_spi_obj_t *)MP_OBJ_TO_PTR(pos_args[0]); + + // get the buffer to read the data into + mp_buffer_info_t readbuf; + mp_get_buffer_raise(args[ARG_readbuf].u_obj, &readbuf, MP_BUFFER_WRITE); + mp_buffer_info_t writebuf; + mp_get_buffer_raise(args[ARG_writebuf].u_obj, &writebuf, MP_BUFFER_READ); + + int length = ((size_t)args[ARG_datasize].u_int > readbuf.len ? readbuf.len : (size_t)args[ARG_datasize].u_int); + + + // do the transfer + int ret = Helios_SPI_WriteRead((Helios_SPINum) self->port,(void*) readbuf.buf, (size_t) length,(void*) writebuf.buf,(size_t)args[ARG_datasize].u_int); + + if (ret < 0) { + HELIOS_SPI_LOG("Helios_SPI_WriteRead ret=%d\r\n",ret); + mp_raise_OSError(-ret); + } + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_KW(machine_spi_write_read_obj, 1, machine_spi_write_read_mem); + +#else +static const mp_arg_t machine_spi_half_duplex_write_read_mem_allowed_args[] = { + { MP_QSTR_readbuf, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_writebuf, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_write_datasize, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_read_datasize, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, +}; +static mp_obj_t machine_spi_half_duplex_write_read_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_readbuf, ARG_writebuf, ARG_write_datasize, ARG_read_datasize }; + mp_arg_val_t args[MP_ARRAY_SIZE(machine_spi_half_duplex_write_read_mem_allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, + MP_ARRAY_SIZE(machine_spi_half_duplex_write_read_mem_allowed_args), machine_spi_half_duplex_write_read_mem_allowed_args, args); + + machine_hard_spi_obj_t *self = (machine_hard_spi_obj_t *)MP_OBJ_TO_PTR(pos_args[0]); + + // get the buffer to read the data into + mp_buffer_info_t readbuf; + mp_get_buffer_raise(args[ARG_readbuf].u_obj, &readbuf, MP_BUFFER_WRITE); + mp_buffer_info_t writebuf; + mp_get_buffer_raise(args[ARG_writebuf].u_obj, &writebuf, MP_BUFFER_READ); + + int write_length = ((size_t)args[ARG_write_datasize].u_int > writebuf.len ? writebuf.len : (size_t)args[ARG_write_datasize].u_int); + int read_length = ((size_t)args[ARG_read_datasize].u_int > readbuf.len ? readbuf.len : (size_t)args[ARG_read_datasize].u_int); + + + // do the transfer + int ret = Helios_SPI_WriteRead((Helios_SPINum) self->port,(void*) readbuf.buf, (size_t) read_length,(void*) writebuf.buf,(size_t)write_length); + + if (ret < 0) { + HELIOS_SPI_LOG("Helios_SPI_WriteRead ret=%d\r\n",ret); + mp_raise_OSError(-ret); + } + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_KW(machine_spi_half_duplex_write_read_obj, 1, machine_spi_half_duplex_write_read_mem); +#endif +static const mp_rom_map_elem_t machine_spi_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&machine_spi_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&machine_spi_write_obj) }, +#ifndef PLAT_SONY_ALT1350 + { MP_ROM_QSTR(MP_QSTR_write_read), MP_ROM_PTR(&machine_spi_write_read_obj) }, +#else + { MP_ROM_QSTR(MP_QSTR_half_duplex_write_read), MP_ROM_PTR(&machine_spi_half_duplex_write_read_obj) }, +#endif +#if !defined(BOARD_EC800GCN_GA) + { MP_ROM_QSTR(MP_QSTR_SPI0), MP_ROM_INT(HELIOS_SPI0) }, +#endif +#if !defined(PLAT_RDA) && !defined(BOARD_EG915UEU_AB) + { MP_ROM_QSTR(MP_QSTR_SPI1), MP_ROM_INT(HELIOS_SPI1) }, +#endif +}; + +MP_DEFINE_CONST_DICT(mp_machine_hard_spi_locals_dict, machine_spi_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + machine_hard_spi_type, + MP_QSTR_SPI, + MP_TYPE_FLAG_NONE, + make_new, machine_hard_spi_make_new, + print, machine_hard_spi_print, + locals_dict, &mp_machine_hard_spi_locals_dict + ); + +#endif diff --git a/ports/quectel/machine_i2c.h b/ports/quectel/machine_i2c.h new file mode 100644 index 0000000000000..a3363d4c341c5 --- /dev/null +++ b/ports/quectel/machine_i2c.h @@ -0,0 +1,90 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * 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. + */ +#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_I2C_H +#define MICROPY_INCLUDED_EXTMOD_MACHINE_I2C_H + +#include "py/obj.h" +#include "py/mphal.h" + +// Temporary support for legacy construction of SoftI2C via I2C type. +#define MP_MACHINE_I2C_CHECK_FOR_LEGACY_SOFTI2C_CONSTRUCTION(n_args, n_kw, all_args) \ + do { \ + if (n_args == 0 || all_args[0] == MP_OBJ_NEW_SMALL_INT(-1)) { \ + mp_print_str(MICROPY_ERROR_PRINTER, "Warning: I2C(-1, ...) is deprecated, use SoftI2C(...) instead\n"); \ + if (n_args != 0) { \ + --n_args; \ + ++all_args; \ + } \ + return mp_machine_soft_i2c_type.make_new(&mp_machine_soft_i2c_type, n_args, n_kw, all_args); \ + } \ + } while (0) + +#define MP_MACHINE_I2C_FLAG_READ (0x01) // if not set then it's a write +#define MP_MACHINE_I2C_FLAG_STOP (0x02) + +#if MICROPY_PY_MACHINE_I2C_TRANSFER_WRITE1 +// If set, the first mp_machine_i2c_buf_t in a transfer is a write. +#define MP_MACHINE_I2C_FLAG_WRITE1 (0x04) +#endif + +typedef struct _mp_machine_i2c_buf_t { + size_t len; + uint8_t *buf; +} mp_machine_i2c_buf_t; + +// I2C protocol +// - init must be non-NULL +// - start/stop/read/write can be NULL, meaning operation is not supported +// - transfer must be non-NULL +// - transfer_single only needs to be set if transfer=mp_machine_i2c_transfer_adaptor +typedef struct _mp_machine_i2c_p_t { + #if MICROPY_PY_MACHINE_I2C_TRANSFER_WRITE1 + bool transfer_supports_write1; + #endif + void (*init)(mp_obj_base_t *obj, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); + int (*start)(mp_obj_base_t *obj); + int (*stop)(mp_obj_base_t *obj); + int (*read)(mp_obj_base_t *obj, uint8_t *dest, size_t len, bool nack); + int (*write)(mp_obj_base_t *obj, const uint8_t *src, size_t len); + int (*transfer)(mp_obj_base_t *obj, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags); + int (*transfer_single)(mp_obj_base_t *obj, uint16_t addr, size_t len, uint8_t *buf, unsigned int flags); +} mp_machine_i2c_p_t; + +typedef struct _mp_machine_soft_i2c_obj_t { + mp_obj_base_t base; + uint32_t us_delay; + uint32_t us_timeout; + mp_hal_pin_obj_t scl; + mp_hal_pin_obj_t sda; +} mp_machine_soft_i2c_obj_t; + +extern const mp_obj_type_t mp_machine_soft_i2c_type; +extern const mp_obj_dict_t mp_machine_i2c_locals_dict; + +int mp_machine_i2c_transfer_adaptor(mp_obj_base_t *self, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags); +int mp_machine_soft_i2c_transfer(mp_obj_base_t *self, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags); + +#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_I2C_H diff --git a/ports/quectel/machine_iic.c b/ports/quectel/machine_iic.c new file mode 100644 index 0000000000000..8cd9408fae2e6 --- /dev/null +++ b/ports/quectel/machine_iic.c @@ -0,0 +1,188 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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 "py/gc.h" +#include "py/mphal.h" +#include "py/mperrno.h" + +#if MICROPY_QPY_MACHINE_I2C + +#include "machine_i2c.h" +#include "helios_iic.h" +#include "mphalport.h" + + +const mp_obj_type_t machine_hard_i2c_type; + +typedef struct _machine_hard_i2c_obj_t { + mp_obj_base_t base; + uint32_t bus_id; + uint32_t fastmode; +} machine_hard_i2c_obj_t; + +static void machine_hard_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + machine_hard_i2c_obj_t *self = self_in; + mp_printf(print, "I2C%d", self->bus_id); +} + +mp_obj_t machine_hard_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_id, ARG_fastmode }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_fastmode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 1} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + uint32_t bus_id = args[ARG_id].u_int; + uint32_t fastmode = args[ARG_fastmode].u_int; + + + if (bus_id > HELIOS_I2C3) { + mp_raise_ValueError(MP_ERROR_TEXT("bus id must be (0~3)")); + } + + volatile machine_hard_i2c_obj_t *self = m_new_obj(machine_hard_i2c_obj_t); + + self->base.type = &machine_hard_i2c_type; + self->bus_id = bus_id; + self->fastmode = fastmode; + if(0 != Helios_I2C_Init((Helios_I2CEnum) self->bus_id, (Helios_I2CMode) self->fastmode)) { + return mp_const_false; + } + return MP_OBJ_FROM_PTR(self); +} +static const mp_arg_t machine_i2c_mem_allowed_args[] = { + { MP_QSTR_slaveaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_regaddr, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_regaddr_len, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_databuf, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_datasize, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 8} }, +}; +static mp_obj_t machine_i2c_write_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_slaveaddr, ARG_regaddr, ARG_regaddr_len, ARG_databuf, ARG_datasize }; + mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, + MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args); + + machine_hard_i2c_obj_t *self = (machine_hard_i2c_obj_t *)MP_OBJ_TO_PTR(pos_args[0]); + + mp_buffer_info_t regaddr_bufinfo; + mp_get_buffer_raise(args[ARG_regaddr].u_obj, ®addr_bufinfo, MP_BUFFER_READ); + int regaddr_length = args[ARG_regaddr_len].u_int; + + // get the buffer to write the data from + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[ARG_databuf].u_obj, &bufinfo, MP_BUFFER_READ); + int length = (size_t)args[ARG_datasize].u_int > bufinfo.len ? bufinfo.len : (size_t)args[ARG_datasize].u_int; + //uart_printf("i2c wirte: busid:%x slaveddr:%x, regaddr:%x, data:%s datalen:%d\n", self->bus_id, args[ARG_slaveaddr].u_int, args[ARG_regaddr].u_int, + // bufinfo.buf, args[ARG_datasize].u_int); + // do the transfer + int ret = HELIOS_I2C_Write((Helios_I2CEnum) self->bus_id, (uint8_t) args[ARG_slaveaddr].u_int, (uint8_t*) regaddr_bufinfo.buf,(size_t) regaddr_length,(void*) bufinfo.buf, (size_t) length); + if (ret < 0) { + ret = -1; + return mp_obj_new_int(ret); + } + + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_write_obj, 1, machine_i2c_write_mem); + +static const mp_arg_t machine_i2c_mem_allowed_read_args[] = { + { MP_QSTR_slaveaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_regaddr, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_regaddr_len, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_databuf, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_datasize, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 8} }, + { MP_QSTR_dalay, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 8} }, +}; +static mp_obj_t machine_i2c_read_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_slaveaddr, ARG_regaddr, ARG_regaddr_len, ARG_databuf, ARG_datasize, ARG_dalay }; + mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_read_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, + MP_ARRAY_SIZE(machine_i2c_mem_allowed_read_args), machine_i2c_mem_allowed_read_args, args); + + machine_hard_i2c_obj_t *self = (machine_hard_i2c_obj_t *)MP_OBJ_TO_PTR(pos_args[0]); + + mp_buffer_info_t regaddr_bufinfo; + mp_get_buffer_raise(args[ARG_regaddr].u_obj, ®addr_bufinfo, MP_BUFFER_READ); + int regaddr_length = (size_t)args[ARG_regaddr_len].u_int > regaddr_bufinfo.len ? regaddr_bufinfo.len : (size_t)args[ARG_regaddr_len].u_int; + + // get the buffer to read the data into + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[ARG_databuf].u_obj, &bufinfo, MP_BUFFER_WRITE); + + int length = (size_t)args[ARG_datasize].u_int > bufinfo.len ? bufinfo.len : (size_t)args[ARG_datasize].u_int; + + //uart_printf("i2c read: busid:%x slaveddr:%x, regaddr:%x, datalen:%d\n", self->bus_id, args[ARG_slaveaddr].u_int, args[ARG_regaddr].u_int, + // args[ARG_datasize].u_int); + // do the transfer + int ret = HELIOS_I2C_Read((Helios_I2CEnum) self->bus_id, (uint8_t) args[ARG_slaveaddr].u_int,(uint8_t*) regaddr_bufinfo.buf, (size_t) regaddr_length, (void*) bufinfo.buf, (size_t) length,(uint32_t) args[ARG_dalay].u_int); + if (ret < 0) { + ret = -1; + return mp_obj_new_int(ret); + } + + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_read_obj, 1, machine_i2c_read_mem); + +static const mp_rom_map_elem_t machine_i2c_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&machine_i2c_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&machine_i2c_write_obj) }, + // class constants + { MP_ROM_QSTR(MP_QSTR_I2C0), MP_ROM_INT(HELIOS_I2C0) }, +#if !defined(PLAT_ASR_1803s) && !defined(BOARD_EC800MCN_LA) && !defined(BOARD_EC800MCN_GA) && !defined(BOARD_EC800NCN_LA) && !defined(BOARD_EC800NCN_LA_VOLTE) + { MP_ROM_QSTR(MP_QSTR_I2C1), MP_ROM_INT(HELIOS_I2C1) }, +#endif +#if !defined(PLAT_RDA) && !defined(BOARD_EC800NCN_LA) && !defined(BOARD_EC800NCN_LA_VOLTE) && !defined(BOARD_EC600GCN_LD) + { MP_ROM_QSTR(MP_QSTR_I2C2), MP_ROM_INT(HELIOS_I2C2) }, +#if !defined(PLAT_Qualcomm) && !defined(BOARD_EC800MCN_LA) && !defined(BOARD_EC800MCN_GA) && !defined(BOARD_EC800GCN_GA) && !defined(BOARD_EC800GCN_LD) && !defined(BOARD_EC800GCN_LD_HRXM) + { MP_ROM_QSTR(MP_QSTR_I2C3), MP_ROM_INT(HELIOS_I2C3) }, +#endif +#endif + { MP_ROM_QSTR(MP_QSTR_STANDARD_MODE), MP_ROM_INT(HELIOS_STANDARD_MODE) }, + { MP_ROM_QSTR(MP_QSTR_FAST_MODE), MP_ROM_INT(HELIOS_FAST_MODE) }, +}; + +MP_DEFINE_CONST_DICT(mp_machine_hard_i2c_locals_dict, machine_i2c_locals_dict_table); + + +MP_DEFINE_CONST_OBJ_TYPE( + machine_hard_i2c_type, + MP_QSTR_I2C, + MP_TYPE_FLAG_NONE, + make_new, machine_hard_i2c_make_new, + print, machine_hard_i2c_print, + locals_dict, &mp_machine_hard_i2c_locals_dict + ); + +#endif diff --git a/ports/quectel/machine_pin.c b/ports/quectel/machine_pin.c new file mode 100644 index 0000000000000..b9953c9f774c1 --- /dev/null +++ b/ports/quectel/machine_pin.c @@ -0,0 +1,333 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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 "py/gc.h" +#include "py/mphal.h" + +#if MICROPY_QPY_MACHINE_PIN + +#include "helios_gpio.h" +#include "helios_debug.h" + + +#define HELIOS_PIN_LOG(msg, ...) custom_log("machine_pin", msg, ##__VA_ARGS__) + +#define GPIO_OBJ_DEF(n) {{&machine_pin_type}, HELIOS_GPIO##n, 0, 0, 0} +#define PLAT_GPIO_OBJ_DEF(n) BOOST_PP_REPEAT_1(n,GPIO_OBJ_DEF) + + +typedef struct _machine_pin_obj_t { + mp_obj_base_t base; + uint pin; + uint dir; + uint pull; + uint value; +} machine_pin_obj_t; + +const mp_obj_type_t machine_pin_type; + + +static machine_pin_obj_t *machine_pin_obj[PLAT_GPIO_NUM] = {NULL}; + + +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, "", self->pin); +} + +// pin.init(mode, pull=None, *, value) +static mp_obj_t machine_pin_obj_init_helper(machine_pin_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_dir, ARG_pull, ARG_value }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_dir, MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_pull, MP_ARG_INT, {.u_int = -1}}, + { MP_QSTR_value, MP_ARG_INT, {.u_int = -1}}, + }; + + // 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); + + // get dir mode + switch (args[ARG_dir].u_int) { + case -1: + break; + case HELIOS_GPIO_INPUT: + case HELIOS_GPIO_OUTPUT: + self->dir = args[ARG_dir].u_int; + break; + default: + mp_raise_ValueError(MP_ERROR_TEXT("invalid pin dir, range{0:dir in, 1:dir out}")); + break; + } + // get pull mode + switch (args[ARG_pull].u_int) { + case -1: + break; + case HELIOS_PULL_NONE: + case HELIOS_PULL_UP: + case HELIOS_PULL_DOWN: + self->pull = args[ARG_pull].u_int; + break; + default: + mp_raise_ValueError(MP_ERROR_TEXT("invalid pin pull, range{0:PIN_PULL_DISABLE, 1:PIN_PULL_PU, 2:PIN_PULL_PD}")); + break; + } + // get initial value + switch (args[ARG_value].u_int) { + case -1: + break; + case HELIOS_LVL_LOW: + case HELIOS_LVL_HIGH: + self->value = args[ARG_value].u_int; + break; + default: + mp_raise_ValueError(MP_ERROR_TEXT("invalid pin value, range{0:PIN_LEVEL_LOW, 1:PIN_LEVEL_HIGH}")); + break; + } + Helios_GPIOInitStruct gpio_struct = {0}; + gpio_struct.dir = self->dir; + gpio_struct.pull = self->pull; + gpio_struct.value = self->value; + HELIOS_PIN_LOG("pin = %d dir = %d, pull = %d value=%d\n",self->pin, self->dir, self->pull, self->value); + int ret = Helios_GPIO_Init((Helios_GPIONum) self->pin, &gpio_struct); + HELIOS_PIN_LOG("gpio init ret = %d\n",ret); + + if (ret != 0){ + mp_raise_ValueError(MP_ERROR_TEXT("GPIO initialization error")); + } + + + return mp_const_none; +} + +// constructor(drv_name, pin, ...) +mp_obj_t mp_pin_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, MP_OBJ_FUN_ARGS_MAX, true); + + // get the wanted pin object + //unsigned int i = 0; + int wanted_pin = 0; + wanted_pin = mp_obj_get_int(args[0]); + + if(wanted_pin == 0 || wanted_pin > PLAT_GPIO_NUM) { + mp_raise_ValueError(MP_ERROR_TEXT("invalid pin")); + } + + HELIOS_PIN_LOG("wanted_pin = %d\n",wanted_pin); + machine_pin_obj_t *self = NULL; + + if (machine_pin_obj[wanted_pin-1] == NULL) + { + machine_pin_obj[wanted_pin-1] = mp_obj_malloc_with_finaliser(machine_pin_obj_t, &machine_pin_type); + } + self = machine_pin_obj[wanted_pin-1]; + self->base.type = &machine_pin_type; + self->pin = wanted_pin; + + // default settings + self->dir = HELIOS_GPIO_OUTPUT; + self->pull = HELIOS_PULL_NONE; + self->value = HELIOS_LVL_LOW; + HELIOS_PIN_LOG("dir = %d, pull = %d value=%d\n",self->dir, self->pull, self->value); + + if (n_args > 1 || n_kw > 0) { + // pin mode given, so configure this GPIO + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + HELIOS_PIN_LOG("n_args = %d\n",n_args); + machine_pin_obj_init_helper(self, n_args - 1, args + 1, &kw_args); + HELIOS_PIN_LOG("n_kw = %d\n",n_kw); + } else { + + Helios_GPIOInitStruct gpio_struct = {0}; + gpio_struct.dir = self->dir; + gpio_struct.pull = self->pull; + gpio_struct.value = self->value; + Helios_GPIO_Init((Helios_GPIONum) self->pin, &gpio_struct); + } + + HELIOS_PIN_LOG("pin init end\n"); + return MP_OBJ_FROM_PTR(self); +} + +// fast method for getting/setting pin value +static mp_obj_t machine_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 0, 1, false); + machine_pin_obj_t *self = self_in; + if (n_args == 0) { + int pin_val = Helios_GPIO_GetLevel((Helios_GPIONum) self->pin); + return MP_OBJ_NEW_SMALL_INT(pin_val); + } else { + Helios_GPIO_SetLevel((Helios_GPIONum) self->pin, (Helios_LvlMode) mp_obj_is_true(args[0])); + return mp_const_none; + } +} + +// pin.init(mode, pull) +static mp_obj_t machine_pin_obj_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { + return machine_pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args); +} +MP_DEFINE_CONST_FUN_OBJ_KW(machine_pin_init_obj, 1, machine_pin_obj_init); + +// pin.value([value]) +static mp_obj_t machine_pin_value(size_t n_args, const mp_obj_t *args) { + return machine_pin_call(args[0], n_args - 1, 0, args + 1); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_value_obj, 1, 2, machine_pin_value); + +static mp_obj_t machine_pin_off(mp_obj_t self_in) { + machine_pin_obj_t *self = self_in; + Helios_GPIO_SetLevel((Helios_GPIONum) self->pin, (Helios_LvlMode) HELIOS_LVL_LOW); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_off_obj, machine_pin_off); + +static mp_obj_t machine_pin_on(mp_obj_t self_in) { + machine_pin_obj_t *self = self_in; + Helios_GPIO_SetLevel((Helios_GPIONum) self->pin, (Helios_LvlMode) HELIOS_LVL_HIGH); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_on_obj, machine_pin_on); + +static mp_obj_t machine_pin_write(mp_obj_t self_in, mp_obj_t value) +{ + machine_pin_obj_t *self = self_in; + int pin_value = mp_obj_get_int(value); + int ret = Helios_GPIO_SetLevel((Helios_GPIONum) self->pin, (Helios_LvlMode) pin_value); + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_2(machine_pin_write_obj, machine_pin_write); + +static mp_obj_t machine_pin_read(size_t n_args, const mp_obj_t *args) +{ + return machine_pin_call(args[0], n_args - 1, 0, args + 1); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_read_obj, 1, 2, machine_pin_read); + + +static mp_uint_t machine_pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { + (void)errcode; + machine_pin_obj_t *self = self_in; + + switch (request) { + case MP_PIN_READ: { + int pin_val = Helios_GPIO_GetLevel((Helios_GPIONum) self->pin); + return pin_val; + } + case MP_PIN_WRITE: { + Helios_GPIO_SetLevel((Helios_GPIONum) self->pin, (Helios_LvlMode) arg); + return 0; + } + } + return -1; +} + +static mp_obj_t machine_pin_set_dir(mp_obj_t self_in, mp_obj_t dir) +{ + machine_pin_obj_t *self = self_in; + int ret = -1; + + int pin_value = mp_obj_get_int(dir); + if((pin_value != HELIOS_GPIO_INPUT) && (pin_value != HELIOS_GPIO_OUTPUT)){ + mp_raise_ValueError(MP_ERROR_TEXT("Invalid direction parameter")); + } + ret = Helios_GPIO_SetDirection((Helios_GPIONum) self->pin, (Helios_GPIODir) pin_value); + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_2(machine_pin_set_dir_obj, machine_pin_set_dir); + +static mp_obj_t machine_pin_get_dir(mp_obj_t self_in) +{ + machine_pin_obj_t *self = self_in; + int ret = Helios_GPIO_GetDirection((Helios_GPIONum) self->pin); + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_get_dir_obj, machine_pin_get_dir); + + +static mp_obj_t machine_pin_deinit(mp_obj_t self_in) { + machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in); + //HELIOS_PIN_LOG("machine pin deinit.pin=%d.\r\n", self->pin); + + machine_pin_obj[self->pin - 1] = NULL; + + int ret = Helios_GPIO_Deinit((Helios_GPIONum)self->pin); + if (ret != 0) + { + HELIOS_PIN_LOG("GPIO%d deinit failed.\r\n", self->pin); + } + return mp_obj_new_int(ret); + +} +static MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_deinit_obj, machine_pin_deinit); + + +static const mp_rom_map_elem_t machine_pin_locals_dict_table[] = { + // instance methods + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&machine_pin_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_pin_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&machine_pin_value_obj) }, + { MP_ROM_QSTR(MP_QSTR_off), MP_ROM_PTR(&machine_pin_off_obj) }, + { MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&machine_pin_on_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&machine_pin_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&machine_pin_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_dir), MP_ROM_PTR(&machine_pin_set_dir_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_dir), MP_ROM_PTR(&machine_pin_get_dir_obj) }, + // class constants + //GPIO DEFINE + { MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(HELIOS_GPIO_INPUT) }, + { MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(HELIOS_GPIO_OUTPUT) }, + { MP_ROM_QSTR(MP_QSTR_PULL_PU), MP_ROM_INT(HELIOS_PULL_UP) }, + { MP_ROM_QSTR(MP_QSTR_PULL_PD), MP_ROM_INT(HELIOS_PULL_DOWN) }, + { MP_ROM_QSTR(MP_QSTR_PULL_DISABLE), MP_ROM_INT(HELIOS_PULL_NONE) }, + PLAT_GPIO_DEF(PLAT_GPIO_NUM), +}; + +static MP_DEFINE_CONST_DICT(machine_pin_locals_dict, machine_pin_locals_dict_table); + +static const mp_pin_p_t machine_pin_pin_p = { + .ioctl = machine_pin_ioctl, +}; + +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, &machine_pin_pin_p, + locals_dict, &machine_pin_locals_dict + ); + +#endif + diff --git a/ports/quectel/machine_rtc.c b/ports/quectel/machine_rtc.c new file mode 100644 index 0000000000000..720e6c0a3d6fc --- /dev/null +++ b/ports/quectel/machine_rtc.c @@ -0,0 +1,228 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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/nlr.h" +#include "py/obj.h" +#include "py/runtime.h" +#include "py/mphal.h" + +#if MICROPY_QPY_MACHINE_RTC + +#include "modmachine.h" +#include "helios_debug.h" +#include "helios_rtc.h" +#include "callbackdeal.h" + +#define HELIOS_RTC_LOG(fmt, ...) custom_log(machine_rtc, fmt, ##__VA_ARGS__) + + +typedef struct _machine_rtc_obj_t { + mp_obj_base_t base; +} machine_rtc_obj_t; + +static c_callback_t *callback_cur = NULL; + + +// singleton RTC object +//static const machine_rtc_obj_t machine_rtc_obj = {{&machine_rtc_type}}; +const mp_obj_type_t machine_rtc_type; +static machine_rtc_obj_t *machine_rtc_obj_ptr = NULL; + + + +static mp_obj_t machine_rtc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + // check arguments + mp_arg_check_num(n_args, n_kw, 0, 0, false); + if (machine_rtc_obj_ptr != NULL) + { + // singleton RTC object + return MP_OBJ_FROM_PTR(machine_rtc_obj_ptr); + } + machine_rtc_obj_ptr = mp_obj_malloc_with_finaliser(machine_rtc_obj_t, &machine_rtc_type); + machine_rtc_obj_ptr->base.type = &machine_rtc_type; + return MP_OBJ_FROM_PTR(machine_rtc_obj_ptr); +} + + + +static mp_obj_t machine_rtc_datetime_helper(mp_uint_t n_args, const mp_obj_t *args) { + //ql_rtc_time_t tm = {0}; //Jayceon-2020/08/27:Resolved that calling the init() function would cause system dump + Helios_RTCTime tm = {0}; + if (n_args == 1) { + // Pawn 2021/4/28 Solve the problem of different initial time zones between RDA and ASR + // Pawn Fix the bug SW1PQUECPYTHON-119 + Helios_RTC_GetLocalTime(&tm); + // Pawn Fix the bug SW1PQUECPYTHON-119 end + 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_wday), + 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(0) + }; + + return mp_obj_new_tuple(8, tuple); + } else { + // Set time + + mp_obj_t *items; + mp_obj_get_array_fixed_n(args[1], 8, &items); + tm.tm_year = mp_obj_get_int(items[0]); + tm.tm_mon = mp_obj_get_int(items[1]); + tm.tm_mday = mp_obj_get_int(items[2]); + tm.tm_hour = mp_obj_get_int(items[4]); + tm.tm_min = mp_obj_get_int(items[5]); + tm.tm_sec = mp_obj_get_int(items[6]); + + //int ret = ql_rtc_set_time(&tm); + + // Pawn Fix the bug SW1PQUECPYTHON-119 + int ret = Helios_RTC_NtpSetTime(&tm, 1); + // Pawn Fix the bug SW1PQUECPYTHON-119 end + + return mp_obj_new_int(ret); + } +} + + +static mp_obj_t machine_rtc_datetime(mp_uint_t n_args, const mp_obj_t *args) { + return machine_rtc_datetime_helper(n_args, args); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_rtc_datetime_obj, 1, 2, (mp_obj_t)machine_rtc_datetime); + +#if !defined(PLAT_Qualcomm) +static mp_obj_t machine_rtc_set_alarm(mp_obj_t self_in, mp_obj_t time) +{ + Helios_RTCTime tm = {0}; + mp_obj_t *items; + + mp_obj_get_array_fixed_n(time, 8, &items); + tm.tm_year = mp_obj_get_int(items[0]); + tm.tm_mon = mp_obj_get_int(items[1]); + tm.tm_mday = mp_obj_get_int(items[2]); + tm.tm_hour = mp_obj_get_int(items[4]); + tm.tm_min = mp_obj_get_int(items[5]); + tm.tm_sec = mp_obj_get_int(items[6]); + + int ret = Helios_RTC_Set_Alarm(&tm); + + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_2(machine_rtc_set_alarm_obj, machine_rtc_set_alarm); + + +static mp_obj_t machine_rtc_enable_alarm(mp_obj_t self_in, mp_obj_t enable) +{ + int on_off = mp_obj_get_int(enable); + + int ret = Helios_RTC_Enable_Alarm((unsigned char)on_off); + + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_2(machine_rtc_enable_alarm_obj, machine_rtc_enable_alarm); + + +void rtc_callback_to_python(void) +{ + if(callback_cur == NULL) { + return; + } + + mp_sched_schedule_ex(callback_cur, mp_const_none); + +#if defined(PLAT_RDA) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) + Helios_Rtc_Set_Called(Helios_Rtc_Call_NoCalled); +#endif +} + + +static mp_obj_t machine_rtc_register_callback(mp_obj_t self_in, mp_obj_t callback) +{ + static c_callback_t cb = {0}; + memset(&cb, 0, sizeof(c_callback_t)); + callback_cur = &cb; + mp_sched_schedule_callback_register(callback_cur, callback); + +#if defined(PLAT_RDA) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) + if ( Helios_Rtc_Get_Called() == Helios_Rtc_Call_Called ) + { + mp_sched_schedule_ex(callback_cur, NULL); + Helios_Rtc_Set_Called(Helios_Rtc_Call_NoCalled); + } +#endif + int ret = Helios_RTC_Register_cb(rtc_callback_to_python); + + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_2(machine_rtc_register_callback_obj, machine_rtc_register_callback); +#endif + +static mp_obj_t machine_rtc_init(mp_obj_t self_in, mp_obj_t date) { + mp_obj_t args[2] = {self_in, date}; + machine_rtc_datetime_helper(2, args); + + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_2(machine_rtc_init_obj, machine_rtc_init); + +static mp_obj_t machine_rtc_deinit(mp_obj_t self_in) { + HELIOS_RTC_LOG("machine rtc deinit.\r\n"); + callback_cur = NULL; + machine_rtc_obj_ptr = NULL; + return mp_obj_new_int(0); +} +static MP_DEFINE_CONST_FUN_OBJ_1(machine_rtc_deinit_obj, machine_rtc_deinit); + + +static const mp_rom_map_elem_t machine_rtc_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_rtc_init_obj) }, + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&machine_rtc_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_datetime), MP_ROM_PTR(&machine_rtc_datetime_obj) }, +#if !defined(PLAT_Qualcomm) + { MP_ROM_QSTR(MP_QSTR_set_alarm), MP_ROM_PTR(&machine_rtc_set_alarm_obj) }, + { MP_ROM_QSTR(MP_QSTR_enable_alarm), MP_ROM_PTR(&machine_rtc_enable_alarm_obj) }, + { MP_ROM_QSTR(MP_QSTR_register_callback), MP_ROM_PTR(&machine_rtc_register_callback_obj) }, +#endif +}; +static MP_DEFINE_CONST_DICT(machine_rtc_locals_dict, machine_rtc_locals_dict_table); + +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 + ); + +#endif /* MICROPY_QPY_MACHINE_RTC */ + diff --git a/ports/quectel/machine_timer.c b/ports/quectel/machine_timer.c new file mode 100644 index 0000000000000..01e9d153305f3 --- /dev/null +++ b/ports/quectel/machine_timer.c @@ -0,0 +1,311 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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/obj.h" +#include "py/runtime.h" +#include "modmachine.h" +#include "mphalport.h" + + +#if MICROPY_QPY_MACHINE_TIMER + +#include "helios_timer.h" +#include "helios_debug.h" +#include "callbackdeal.h" + + +typedef unsigned long int UINT32; +#define HELIOS_TIMER_LOG(msg, ...) custom_log("machine_timer", msg, ##__VA_ARGS__) + + +typedef enum +{ + Timer0 = 0, + Timer1 = 1, + Timer2 = 2, + Timer3 = 3 +}Timern; + +typedef enum /* The meaning of the API flag*/ +{ + TIMER_PERIODIC = 0x1, /* periodic execution */ + TIMER_AUTO_DELETE = 0x2 /* one execution */ +}TIMER_FLAG; + +typedef enum +{ + MP_TIMER_CREATED, + MP_TIMER_RUNNING, + MP_TIMER_STOP +}MP_TIMER_STATUS; + +typedef struct _machine_timer_obj_t { + mp_obj_base_t base; + //ONE_SHOT OR PERIODIC + mp_uint_t mode; + mp_uint_t period; + c_callback_t callback; + mp_int_t timer_id; + mp_int_t timer_id_real; + MP_TIMER_STATUS timer_status; + //for traverse all the timers, such as soft reset while input CTRL+B + struct _machine_timer_obj_t *next; +} machine_timer_obj_t; + +static void machine_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + (void)(print); + (void)(kind); + machine_timer_obj_t *self = self_in; + HELIOS_TIMER_LOG("period=%d\r\n", self->period); + HELIOS_TIMER_LOG("timer_id=%d\r\n", self->timer_id); +} + +#if defined(BOARD_BC32RA) || defined(BOARD_BC92RB) || defined(PLAT_SONY_ALT1350)//forrest.liu@20231228 add for FAE-102027 dump issue +#define HELIOS_TIMER_MAX_NUM (4) +static st_CallBack_Timer Timer_t[HELIOS_TIMER_MAX_NUM] = {{{0,0,0,0,0}},{{0,0,0,0,0}},{{0,0,0,0,0}},{{0,0,0,0,0}}}; +#endif + +static void machine_timer_isr(UINT32 self_in) { + + machine_timer_obj_t *self = (void*)self_in; + if(self != NULL) + { + #if defined(BOARD_BC32RA) || defined(BOARD_BC92RB) || defined(PLAT_SONY_ALT1350)//forrest.liu@20231228 modify for FAE-102027 dump issue + Timer_t[self->timer_id].callback = self->callback; + qpy_send_msg_to_callback_deal_thread(CALLBACK_TYPE_ID_TIMER, &Timer_t[self->timer_id]); + #else + mp_sched_schedule_ex(&self->callback, self); + #endif + } + +} + + +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) { + 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 = TIMER_PERIODIC} }, + { MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { 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} }, + #if MICROPY_PY_BUILTINS_FLOAT + { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + #else + { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} }, + #endif + }; + + int ret; + + 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 MICROPY_PY_BUILTINS_FLOAT + if (args[ARG_freq].u_obj != mp_const_none) { + self->period = (mp_uint_t)(1000 / mp_obj_get_float(args[ARG_freq].u_obj)); + } + #else + if (args[ARG_freq].u_int != 0xffffffff) { + self->period = 1000 / ((mp_uint_t)args[ARG_freq].u_int); + } + #endif + else { + self->period = (((uint64_t)args[ARG_period].u_int) * 1000) / args[ARG_tick_hz].u_int; + } + + self->mode = args[ARG_mode].u_int; + + mp_sched_schedule_callback_register(&self->callback, args[ARG_callback].u_obj); + + HELIOS_TIMER_LOG("mode: %d, period: %d,callback:%#X\r\n", self->mode, self->period,self->callback.cb); + +// Check whether the timer is already running, if so return 0 + if (MP_TIMER_RUNNING == self->timer_status) { + return mp_obj_new_int(0); + } + + int timer = 0; + if(0 == self->timer_id_real) + { + + if(!self) + { + HELIOS_TIMER_LOG("timer test 147!\n"); + } + HELIOS_TIMER_LOG("self = %x\n",self); + timer = Helios_Timer_init( (void* )machine_timer_isr, self); + } + else + { + HELIOS_TIMER_LOG("timer test 153!\n"); + timer = self->timer_id_real; + } + + if(!timer) { + return mp_const_false; + } + + uint8_t cyclicalEn = 0; + if(self->mode == TIMER_PERIODIC) { + cyclicalEn = 1; + } + HELIOS_TIMER_LOG("timer test 165!\n"); + ret = Helios_Timer_Start(timer, (uint32_t) self->period, cyclicalEn); + HELIOS_TIMER_LOG("timer test 167!\n"); + + if(!ret) + { + //get time_id_real + HELIOS_TIMER_LOG("timer_id: %#x\r\n", timer); + self->timer_id_real = timer; + self->timer_status = MP_TIMER_RUNNING; + } + else + { + HELIOS_TIMER_LOG("timer create failed.ret=%d\r\n",ret); + } + return mp_obj_new_int(0); +} + + + +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) { + (void)(type); + mp_int_t timer_id=0; + + if (n_args > 0) { + timer_id = mp_obj_get_int(args[0]); + --n_args; + ++args; + } + + if ((timer_id < 0) || (timer_id > 3)) + { + mp_raise_ValueError(MP_ERROR_TEXT("invalid value, Timern should be in (Timer0~Timer3).")); + } + + machine_timer_obj_t *self = m_new_obj(machine_timer_obj_t); + self->base.type = &machine_timer_type; + self->timer_id = timer_id; + self->timer_id_real = 0; + self->timer_status = MP_TIMER_CREATED; + + 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]); + + 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_stop(mp_obj_t self_in) { + machine_timer_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if(self->timer_id_real) + { + HELIOS_TIMER_LOG("machine_timer_stop (%#X) \r\n",self->timer_id_real); + Helios_Timer_Stop(self->timer_id_real); + self->timer_status = MP_TIMER_STOP; + return mp_obj_new_int(0); + } + return mp_obj_new_int(-1); +} + +static MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_stop_obj, machine_timer_stop); + + +static mp_obj_t machine_timer_deinit(mp_obj_t self_in) { + machine_timer_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if(self->timer_id_real) + { + HELIOS_TIMER_LOG("machine_timer_deinit (%#X) \r\n",self->timer_id_real); + Helios_Timer_Stop(self->timer_id_real); + Helios_Timer_Deinit(self->timer_id_real); + self->timer_id_real = 0; + self->timer_status = MP_TIMER_STOP; + return mp_obj_new_int(0); + } + return mp_obj_new_int(-1); +} + +static MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_deinit_obj, machine_timer_deinit); + + +static mp_obj_t machine_timer_initialize() { + static int initialized = 0; + if (!initialized) { + + HELIOS_TIMER_LOG("machine_timer_initialize\r\n"); + initialized = 1; + } + return mp_const_none; +} + +static MP_DEFINE_CONST_FUN_OBJ_0(machine_timer_initialize_obj, machine_timer_initialize); + +static const mp_rom_map_elem_t machine_timer_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&machine_timer_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&machine_timer_initialize_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&machine_timer_stop_obj) }, + { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&machine_timer_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_ONE_SHOT), MP_ROM_INT(TIMER_AUTO_DELETE) }, + { MP_ROM_QSTR(MP_QSTR_PERIODIC), MP_ROM_INT(TIMER_PERIODIC) }, + { MP_ROM_QSTR(MP_QSTR_Timer0), MP_ROM_INT(Timer0) }, + { MP_ROM_QSTR(MP_QSTR_Timer1), MP_ROM_INT(Timer1) }, + { MP_ROM_QSTR(MP_QSTR_Timer2), MP_ROM_INT(Timer2) }, + { MP_ROM_QSTR(MP_QSTR_Timer3), MP_ROM_INT(Timer3) }, +}; +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 diff --git a/ports/quectel/machine_uart.c b/ports/quectel/machine_uart.c new file mode 100644 index 0000000000000..a52d7d1e3db69 --- /dev/null +++ b/ports/quectel/machine_uart.c @@ -0,0 +1,492 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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 + +#include "runtime.h" +#include "stream.h" +#include "mperrno.h" +#include "mphalport.h" + +#if MICROPY_QPY_MACHINE_UART + +#include "helios_uart.h" +#include "helios_pin.h" +#include "helios_debug.h" +#include "callbackdeal.h" + +typedef struct _machine_uart_obj_t { + mp_obj_base_t base; + unsigned int uart_num; + Helios_UARTConfig config; +} machine_uart_obj_t; + +static c_callback_t *callback_cur[HELIOS_UARTMAX] = {0}; + +static machine_uart_obj_t *uart_self_obj[HELIOS_UARTMAX] = {0}; + + +const mp_obj_type_t machine_uart_type; +static const char *_parity_name[] = {"None", "1", "0"}; + +/******************************************************************************/ +// MicroPython bindings for UART + +static void machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=%s, stop=%u, flow=%u", + self->uart_num, self->config.baudrate, self->config.data_bit, _parity_name[self->config.parity_bit], + self->config.stop_bit, self->config.flow_ctrl); + mp_printf(print, ")"); +} + +static void machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_flow}; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_bits, MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_parity, MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_stop, MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_flow, 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); + + // get baudrate bits + switch (args[ARG_baudrate].u_int) { + case HELIOS_UART_BAUD_300: + case HELIOS_UART_BAUD_600: + case HELIOS_UART_BAUD_1200: + case HELIOS_UART_BAUD_2400: + case HELIOS_UART_BAUD_3600: + case HELIOS_UART_BAUD_4800: + case HELIOS_UART_BAUD_7200: + case HELIOS_UART_BAUD_9600: + case HELIOS_UART_BAUD_14400: + case HELIOS_UART_BAUD_19200: + case HELIOS_UART_BAUD_28800: + case HELIOS_UART_BAUD_33600: + case HELIOS_UART_BAUD_38400: + case HELIOS_UART_BAUD_57600: + case HELIOS_UART_BAUD_115200: + case HELIOS_UART_BAUD_230400: + case HELIOS_UART_BAUD_460800: + case HELIOS_UART_BAUD_921600: + case HELIOS_UART_BAUD_1000000: + case HELIOS_UART_BAUD_1842000: + case HELIOS_UART_BAUD_3686400: + case HELIOS_UART_BAUD_4468750: + self->config.baudrate = args[ARG_baudrate].u_int; + break; + default: + mp_raise_ValueError(MP_ERROR_TEXT("invalid baudrate")); + break; + } + + // get data bits +#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_Unisoc_8910_R06) + switch (args[ARG_bits].u_int) { + case 8: + self->config.data_bit = HELIOS_UART_DATABIT_8; + break; + default: + mp_raise_ValueError(MP_ERROR_TEXT("invalid data bits, Unisoc platform only support 8 data bit.")); + break; + } +#else + switch (args[ARG_bits].u_int) { + case 5: + self->config.data_bit = HELIOS_UART_DATABIT_5; + break; + case 6: + self->config.data_bit = HELIOS_UART_DATABIT_6; + break; + case 7: + self->config.data_bit = HELIOS_UART_DATABIT_7; + break; + case 8: + self->config.data_bit = HELIOS_UART_DATABIT_8; + break; + default: + mp_raise_ValueError(MP_ERROR_TEXT("invalid data bits")); + break; + } +#endif + // get parity bits + switch (args[ARG_parity].u_int) { + case 0: + self->config.parity_bit = HELIOS_UART_PARITY_NONE; + break; + case 1: + self->config.parity_bit = HELIOS_UART_PARITY_EVEN; + break; + case 2: + self->config.parity_bit = HELIOS_UART_PARITY_ODD; + break; + #if defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1602) + case 3: + self->config.parity_bit = HELIOS_UART_PARITY_MARK; + break; + case 4: + self->config.parity_bit = HELIOS_UART_PARITY_SPACE; + break; + #endif + default: + mp_raise_ValueError(MP_ERROR_TEXT("invalid parity bits")); + break; + } + + // get stop bits + switch (args[ARG_stop].u_int) { + case 1: + self->config.stop_bit = HELIOS_UART_STOP_1; + break; + case 2: + self->config.stop_bit = HELIOS_UART_STOP_2; + break; + default: + mp_raise_ValueError(MP_ERROR_TEXT("invalid stop bits")); + break; + } + + // get flow bits + switch (args[ARG_flow].u_int) { + case 0: + self->config.flow_ctrl = HELIOS_UART_FC_NONE; + break; + case 1: + self->config.flow_ctrl = HELIOS_UART_FC_HW; + break; + default: + mp_raise_ValueError(MP_ERROR_TEXT("invalid flow bits")); + break; + } + Helios_UARTInitStruct uart_para = {0}; + Helios_UARTConfig uart_config = {0}; + uart_para.uart_config = &uart_config; + + memcpy((void*)&uart_config,(void*)&self->config, sizeof(Helios_UARTConfig)); + if(self->uart_num == QPY_REPL_UART) { + mp_hal_port_open(0); + } +//Helios_UART_Init has created a timer in kernal and Helios_UART_Deinit will delete this timer of Sony. +//So if we deint uart first, moudle will dump. +#ifndef PLAT_SONY_ALT1350 + Helios_UART_Deinit((Helios_UARTNum) self->uart_num); +#endif + + if(Helios_UART_Init((Helios_UARTNum) self->uart_num, &uart_para) != 0) { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("UART(%d) init fail"), self->uart_num); + } +} + +static mp_obj_t machine_uart_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, MP_OBJ_FUN_ARGS_MAX, true); + + // get uart id + mp_int_t uart_num = mp_obj_get_int(args[0]); + if (uart_num < HELIOS_UART0 || uart_num > HELIOS_UARTMAX) { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("UART(%d) does not exist"), uart_num); + } + + // create instance + if (uart_self_obj[uart_num] == NULL) + { + uart_self_obj[uart_num] = mp_obj_malloc_with_finaliser(machine_uart_obj_t, &machine_uart_type); + } + machine_uart_obj_t *self = uart_self_obj[uart_num]; + + self->base.type = &machine_uart_type; + self->uart_num = uart_num; + self->config.baudrate = HELIOS_UART_BAUD_115200; + self->config.data_bit = HELIOS_UART_DATABIT_8; + self->config.stop_bit = HELIOS_UART_STOP_1; + self->config.parity_bit = HELIOS_UART_PARITY_NONE; + self->config.flow_ctrl = HELIOS_UART_FC_NONE; + + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + machine_uart_init_helper(self, n_args - 1, args + 1, &kw_args); + + return MP_OBJ_FROM_PTR(self); +} + +static mp_obj_t machine_uart_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { + machine_uart_init_helper(args[0], n_args - 1, args + 1, kw_args); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(machine_uart_init_obj, 1, machine_uart_init); + +static mp_obj_t machine_uart_deinit(mp_obj_t self_in) { + machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + + int ret = Helios_UART_Deinit((Helios_UARTNum) self->uart_num); + if(self->uart_num == QPY_REPL_UART) { + mp_hal_port_open(1); + } + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_deinit_obj, machine_uart_deinit); + + +static mp_obj_t machine_uart_any(mp_obj_t self_in) { + machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + size_t rxbufsize; + rxbufsize = Helios_UART_Any((Helios_UARTNum) self->uart_num); + return MP_OBJ_NEW_SMALL_INT(rxbufsize); +} +static MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_any_obj, machine_uart_any); + +#if defined (PLAT_ASR) || defined (PLAT_Unisoc) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_Unisoc_8850) || defined(PLAT_Unisoc_8850_R02) \ + || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_EIGEN) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_ASR_1602) || defined(PLAT_aic8800m40) || defined(PLAT_Unisoc_8910_R06) +enum{ARG_self, ARG_gipo_n, ARG_direc, ARG_block}; +static mp_obj_t machine_uart_485_control(mp_uint_t n_args, const mp_obj_t *args){ + int ret = -1; + if(n_args < 3) + { + mp_raise_ValueError(MP_ERROR_TEXT("invalid parameter")); + } + machine_uart_obj_t *self = MP_OBJ_TO_PTR(args[ARG_self]); + size_t gpio = mp_obj_get_int(args[ARG_gipo_n]); + Helios_UART_Direc dire = (Helios_UART_Direc)mp_obj_get_int(args[ARG_direc]); + ret = Helios_UART_SetCtl_485(self->uart_num,gpio,dire); +#if defined(PLAT_Unisoc_8850) + int set = 0; + if(n_args >= 4) + { + set = mp_obj_get_int(args[ARG_block]); + } + Helios_UART_SetBlockMode_485((char)set); +#endif + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_uart_485_control_obj, 3, 4, (mp_obj_t)machine_uart_485_control); + +#endif + +void helios_uart_callback_to_python(uint64_t ind_type, Helios_UARTNum port, uint64_t size) +{ + if(callback_cur[port] == NULL) { + return; + } + st_CallBack_Uart *Uart_t = malloc(sizeof(st_CallBack_Uart)); + if(NULL != Uart_t) + { + Uart_t->ind_type = ind_type; + Uart_t->port = port; + Uart_t->size = size; + Uart_t->callback = *callback_cur[port]; + qpy_send_msg_to_callback_deal_thread(CALLBACK_TYPE_ID_UART, Uart_t); + } +} + + + +static mp_obj_t helios_uart_set_callback(mp_obj_t self_in, mp_obj_t callback) +{ + machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + static c_callback_t cb[sizeof(callback_cur) / sizeof(callback_cur[0])] = {0}; + memset(&cb[self->uart_num], 0, sizeof(c_callback_t)); + cb[self->uart_num].arg = mp_obj_new_tuple(3, NULL); + callback_cur[self->uart_num] = &cb[self->uart_num]; + mp_sched_schedule_callback_register(callback_cur[self->uart_num], callback); + + int ret = Helios_UART_SetCallback((Helios_UARTNum) self->uart_num, (Helios_UARTCallback) helios_uart_callback_to_python); + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_2(machine_uart_set_callback_obj, helios_uart_set_callback); + +static mp_obj_t helios_uart_deinit(mp_obj_t self_in) +{ + int ret = 0; + + machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + + uart_self_obj[self->uart_num] = NULL; + callback_cur[self->uart_num] = NULL; + ret = Helios_UART_Deinit((Helios_UARTNum) self->uart_num); + + if(self->uart_num == QPY_REPL_UART) { + mp_hal_port_open(1); + } + + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_1(helios_uart_deinit_obj, helios_uart_deinit); + +#if defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) +static mp_obj_t machine_uart_rx_disable(mp_obj_t self_in,mp_obj_t set) +{ + int ret = -1; + machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + size_t set_value = mp_obj_get_int(set); + if(set_value > 1) + { + mp_raise_ValueError(MP_ERROR_TEXT("setting_value must be 0 or 1")); + } + ret = Helios_Uart_Disable_Rx(self->uart_num,set_value); + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_2(machine_uart_rx_disable_obj, machine_uart_rx_disable); +#endif + +static const mp_rom_map_elem_t machine_uart_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&helios_uart_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_uart_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_close), 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_read), MP_ROM_PTR(&mp_stream_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_callback), MP_ROM_PTR(&machine_uart_set_callback_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_writeOnce), MP_ROM_PTR(&mp_stream_write1_obj) }, + { MP_ROM_QSTR(MP_QSTR_readOnce), MP_ROM_PTR(&mp_stream_read1_obj) }, + +#if defined(PLAT_RDA) + { MP_ROM_QSTR(MP_QSTR_UART1), MP_ROM_INT(HELIOS_UART1) }, +#endif +#if defined (PLAT_ASR) || defined (PLAT_Unisoc) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_Unisoc_8850) || defined(PLAT_Unisoc_8850_R02) \ + || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_EIGEN) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_ASR_1602) || defined(PLAT_aic8800m40) || defined(PLAT_Unisoc_8910_R06) + { MP_ROM_QSTR(MP_QSTR_control_485), MP_ROM_PTR(&machine_uart_485_control_obj) }, + PLAT_GPIO_DEF(PLAT_GPIO_NUM), +#endif +#if defined (PLAT_ASR) || defined(PLAT_Qualcomm) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_EIGEN) \ + || defined(PLAT_ASR_1602) || defined(PLAT_ECR6600) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(BOARD_BC32RA) || defined(BOARD_BC92RB) \ + || defined(PLAT_EIGEN_718) || defined(PLAT_aic8800m40) + { MP_ROM_QSTR(MP_QSTR_UART0), MP_ROM_INT(HELIOS_UART0) }, +#endif + +#if !defined(PLAT_RDA) +#if !defined(PLAT_ECR6600) + { MP_ROM_QSTR(MP_QSTR_UART1), MP_ROM_INT(HELIOS_UART1) }, +#endif + { MP_ROM_QSTR(MP_QSTR_UART2), MP_ROM_INT(HELIOS_UART2) }, +#if !defined(PLAT_ECR6600) + { MP_ROM_QSTR(MP_QSTR_UART3), MP_ROM_INT(HELIOS_UART3) }, +#endif +#endif + +#if defined(PLAT_Qualcomm) \ + || defined (PLAT_Unisoc) \ + || defined(PLAT_Unisoc_8910_R05) \ + || defined(PLAT_Unisoc_8910_R06) \ + || defined(BOARD_EC600GCN_LD) \ + || defined(BOARD_EC600GCN_LA) \ + || defined(BOARD_EC600GCN_LA_CDD) \ + || defined(BOARD_EC600GCN_LD_YM) \ + || defined(BOARD_EG700GCN_LC) \ + || defined (PLAT_ASR) \ + || MICROPY_QPY_UART4 + { MP_ROM_QSTR(MP_QSTR_UART4), MP_ROM_INT(HELIOS_UART4) }, +#endif + +#if defined(PLAT_Unisoc_8850) || defined(PLAT_Unisoc_8850_R02) || MICROPY_QPY_USB_DOUBLE_CDC + { MP_ROM_QSTR(MP_QSTR_UART5), MP_ROM_INT(HELIOS_UART5) }, +#endif + +#if defined(PLAT_Unisoc_8850) || defined(PLAT_Unisoc_8850_R02) + { MP_ROM_QSTR(MP_QSTR_UART6), MP_ROM_INT(HELIOS_UART6) }, +#endif + +#if defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) + { MP_ROM_QSTR(MP_QSTR_rx_auto_disable), MP_ROM_PTR(&machine_uart_rx_disable_obj) }, +#endif + { MP_ROM_QSTR(MP_QSTR_REPL_UART), MP_ROM_INT(QPY_REPL_UART) }, +}; + +static MP_DEFINE_CONST_DICT(machine_uart_locals_dict, machine_uart_locals_dict_table); + +static mp_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) { + machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + + // make sure we want at least 1 char + if (size == 0) { + return 0; + } + + int bytes_read = Helios_UART_Read((Helios_UARTNum) self->uart_num, buf_in, size); + if (bytes_read < 0) { + *errcode = MP_EAGAIN; + return MP_STREAM_ERROR; + } + + return bytes_read; +} + +static mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) { + machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + int bytes_written = Helios_UART_Write((Helios_UARTNum) self->uart_num, (void*)buf_in, size); + if (bytes_written < 0) { + *errcode = MP_EAGAIN; + return MP_STREAM_ERROR; + } + + // return number of bytes written + return bytes_written; +} + +static mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { + //machine_uart_obj_t *self = self_in; + mp_uint_t ret; + if (request == MP_STREAM_POLL) { + mp_uint_t flags = (mp_uint_t)arg; + ret = 0; + size_t rxbufsize = 1; + if ((flags & MP_STREAM_POLL_RD) && rxbufsize > 0) { + ret |= MP_STREAM_POLL_RD; + } + if ((flags & MP_STREAM_POLL_WR) && 1) { // FIXME: uart_tx_any_room(self->uart_num) + ret |= MP_STREAM_POLL_WR; + } + } else { + *errcode = MP_EINVAL; + ret = MP_STREAM_ERROR; + } + return ret; +} + +static const mp_stream_p_t uart_stream_p = { + .read = machine_uart_read, + .write = machine_uart_write, + .ioctl = machine_uart_ioctl, + .is_text = false, +}; + +MP_DEFINE_CONST_OBJ_TYPE( + machine_uart_type, + MP_QSTR_UART, + MP_TYPE_FLAG_NONE, + make_new, machine_uart_make_new, + print, machine_uart_print, + protocol, &uart_stream_p, + locals_dict, &machine_uart_locals_dict + ); + +#endif diff --git a/ports/quectel/machine_wdt.c b/ports/quectel/machine_wdt.c new file mode 100644 index 0000000000000..7ef3b6eda2146 --- /dev/null +++ b/ports/quectel/machine_wdt.c @@ -0,0 +1,101 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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 "modmachine.h" +#include "mphalport.h" +#include "py/obj.h" +#include "py/mphal.h" +#include "py/smallint.h" +#include "utime_mphal.h" + +#include "helios_wdt.h" +typedef struct _machine_wdt_init_t +{ + mp_obj_base_t base; +}machine_wdt_init_t; +const mp_obj_type_t machine_wdt_type; + +typedef struct _machine_wdt_obj_t +{ + int status; // Y/N + int period; +}machine_wdt_obj_t; + +static machine_wdt_init_t machine_wdt_obj = {0}; + +static mp_obj_t machine_wdt_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, true); + + machine_wdt_init_t *self = &machine_wdt_obj; + machine_wdt_obj_t info = {0}; + self->base.type = &machine_wdt_type; + if (n_args > 0) + { + info.period = mp_obj_get_int(args[0]); + --n_args; + ++args; + } + Helios_WDT_Deinit(); + if(0 != Helios_WDT_Init((uint64_t) info.period)) { + return mp_const_false; + } + return MP_OBJ_FROM_PTR(self); +} + + +static mp_obj_t machine_wdt_feed(const mp_obj_t arg0) +{ + Helios_WDT_Feed(); + return mp_obj_new_int(0); +} +static MP_DEFINE_CONST_FUN_OBJ_1(machine_wdt_feed_obj, machine_wdt_feed); + + +static mp_obj_t machine_wdt_stop(const mp_obj_t arg0) +{ + Helios_WDT_Deinit(); + return mp_obj_new_int(0); +} +static MP_DEFINE_CONST_FUN_OBJ_1(machine_wdt_stop_obj, machine_wdt_stop); + + +static const mp_rom_map_elem_t machine_wdt_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_feed), MP_ROM_PTR(&machine_wdt_feed_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&machine_wdt_stop_obj) }, +}; +static MP_DEFINE_CONST_DICT(machine_wdt_locals_dict, machine_wdt_locals_dict_table); + +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/quectel/main.c b/ports/quectel/main.c new file mode 100644 index 0000000000000..71b6a2ae8969f --- /dev/null +++ b/ports/quectel/main.c @@ -0,0 +1,312 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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 + +#include "py/builtin.h" +#include "py/compile.h" +#include "py/runtime.h" +#include "py/repl.h" +#include "py/gc.h" +#include "py/mperrno.h" +#include "py/objmodule.h" +#include "py/stackctrl.h" +#include "py/mphal.h" +#include "shared/runtime/pyexec.h" +#include "shared/readline/readline.h" +#include "shared/runtime/gchelper.h" +#include +#include "helios.h" +#include "helios_os.h" +#include "helios_debug.h" +#include "mphalport.h" +#include "callbackdeal.h" +#if MICROPY_KBD_EXCEPTION +#include "shared/runtime/interrupt_char.h" +#endif + +#if CONFIG_MBEDTLS +#include "mbedtls_init.h" +#endif + + +Helios_Thread_t ql_micropython_task_ref; + + +#define MP_TASK_STACK_SIZE (MP_QPY_TASK_STACK_SIZE) +#define MP_TASK_STACK_LEN (MP_TASK_STACK_SIZE/sizeof(uint32_t)) + +#if (defined(PLAT_ASR) || defined(PLAT_Unisoc) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_Qualcomm) \ + || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_Unisoc_8910_R06) || defined(PLAT_ASR_1602)) //support +#define QPY_ASSERT_SUPPORT 1 +#endif + +void nlr_jump_fail(void *val) { +#if QPY_ASSERT_SUPPORT + Helios_Assert(__func__, __FILE__, __LINE__, ""); +#endif + while(1); +} + +void NORETURN __fatal_error(const char *msg) { +#if QPY_ASSERT_SUPPORT + Helios_Assert(msg, __FILE__, __LINE__, ""); +#endif + while(1); +} + +#ifndef NDEBUG +#if !defined(PLAT_Qualcomm) +void MP_WEAK __assert_func(const char *file, int line, const char *func, const char *expr) { +#if QPY_ASSERT_SUPPORT + Helios_Assert(expr, file, line, ""); +#else + printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line); +#endif + __fatal_error("Assertion failed"); +} + +#else +void __assert_fail(const char *__message, + const char *__file, int __line, + const char *__function) { +#if QPY_ASSERT_SUPPORT + Helios_Assert(__message, __file, __line, ""); +#else + printf("Assertion '%s' failed, at file %s:%d\n", __message, __file, __line); +#endif + __fatal_error("Assertion failed"); +} +#endif + +#endif + +static char *stack_top; +#if MICROPY_ENABLE_GC +#if defined(PLAT_ECR6600) +static char __attribute__((__section__(".data"))) heap[MICROPY_GC_HEAP_SIZE]; +#elif defined(PLAT_SONY_ALT1350) +static char __attribute__((__section__("gpm1_working_data"))) heap[MICROPY_GC_HEAP_SIZE]; +#else +static char heap[MICROPY_GC_HEAP_SIZE]; +#endif +#endif + +extern pyexec_mode_kind_t pyexec_mode_kind; + +#if MICROPY_PY_KBD_EXCEPTION +MAINPY_RUNNING_FLAG_DEF +MAINPY_INTERRUPT_BY_KBD_FLAG_DEF +SET_MAINPY_RUNNING_TIMER_DEF +#endif + +#if MICROPY_PY_SOFT_RESET +static int vm_softreset_flag = 0; +#define SOFTRESET_FLAG_SET() vm_softreset_flag = 1; +#define SOFTRESET_FLAG_CLEAR() vm_softreset_flag = 0; +#define SOFTRESET_FLAG_TRUE() (1 == vm_softreset_flag) +#define SOFTRESET_FLAG_FALSE() (0 == vm_softreset_flag) +#endif +void quecpython_task(void *arg) +{ + int stack_dummy; + Helios_Thread_t id = 0; + void *stack_ptr = NULL; + #if MICROPY_QPY_MODULE_POC && CONFIG_POC_BND_XIN + helios_debug( "start qpy_poc_register_task"); + extern void qpy_poc_register_task(); + qpy_poc_register_task(); + #endif + mp_mthread_sleep_deal_init(); + +#if CONFIG_MBEDTLS + mbedtls_platform_setup(NULL); +#endif + + #if MICROPY_PY_THREAD + id = Helios_Thread_GetID(); + ql_micropython_task_ref = id; + stack_ptr = Helios_Thread_GetStaskPtr(id); +#if defined(PLAT_ECR6600) || defined(PLAT_aic8800m40) + mp_thread_init(stack_ptr, MP_TASK_STACK_SIZE); // unit: Word +#else + mp_thread_init(stack_ptr, MP_TASK_STACK_LEN); +#endif + #endif + + if(mp_hal_stdio_init()) return; + +soft_reset: + mp_stack_set_top((void *)&stack_dummy); +#if defined(PLAT_ECR6600) || defined(PLAT_aic8800m40) // unit: Byte + mp_stack_set_limit(MP_TASK_STACK_SIZE * sizeof(uint32_t) - 1024); +#else + mp_stack_set_limit(MP_TASK_STACK_SIZE - 1024); +#endif + stack_top = (char*)&stack_dummy; + #if MICROPY_ENABLE_GC + gc_init(heap, heap + sizeof(heap)); + #endif + mp_init(); + #if MICROPY_ENABLE_CALLBACK_DEAL + qpy_callback_deal_init(); + #endif + readline_init0(); + + // run boot-up scripts +#if defined(PLAT_RDA) + pyexec_frozen_module("_boot_RDA.py"); +#elif defined(PLAT_Qualcomm) + pyexec_frozen_module("_boot_Qualcomm.py"); +#elif defined(BOARD_EC800ECN_LC_WDF) + pyexec_frozen_module("_boot_WDF.py");//EIGEN WDF CUNSTOMER BOOT WITH SINGEL FILE SYSTEM +#elif defined(PLAT_ECR6600) || defined(PLAT_aic8800m40) + pyexec_frozen_module("_boot_WIFI.py"); +#elif defined(BOARD_EC600GCN_LA_CDD) + pyexec_frozen_module("_boot_dsds.py"); +#elif defined(PLAT_SONY_ALT1350) + pyexec_frozen_module("_boot_SONY.py", false); +#else + pyexec_frozen_module("_boot.py", false); +#endif + + if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL + #if MICROPY_PY_KBD_EXCEPTION + && MAINPY_INTERRUPT_BY_KBD_FLAG_FALSE() + #endif + ) + { + #if MICROPY_PY_SOFT_RESET + SOFTRESET_FLAG_CLEAR(); + #endif + + #if MICROPY_PY_KBD_EXCEPTION + MAINPY_RUNNING_FLAG_SET(); + #endif + + int ret = pyexec_file_if_exists("/usr/main.py"); + if (ret & PYEXEC_FORCED_EXIT) { + goto soft_reset_exit; + } + + #if MICROPY_PY_KBD_EXCEPTION + MAINPY_RUNNING_FLAG_CLEAR(); + if(RET_KBD_INTERRUPT == ret) + { + MAINPY_INTERRUPT_BY_KBD_FLAG_SET(); + } + #endif + + #if MICROPY_PY_SOFT_RESET + if((PYEXEC_SOFTRESET & ret) == PYEXEC_SOFTRESET) { + SOFTRESET_FLAG_SET(); + } + #endif + } + else + { + #if MICROPY_PY_KBD_EXCEPTION + MAINPY_INTERRUPT_BY_KBD_FLAG_CLEAR(); + #endif + #if MICROPY_PY_SOFT_RESET + SOFTRESET_FLAG_CLEAR(); + #endif + } + + if(1 + #if MICROPY_PY_KBD_EXCEPTION + && MAINPY_INTERRUPT_BY_KBD_FLAG_FALSE() + #endif + #if MICROPY_PY_SOFT_RESET + && SOFTRESET_FLAG_FALSE() + #endif + ) + { + #if MICROPY_PY_SOFT_RESET + nlr_buf_t nlr; + nlr.ret_val = NULL; + if (nlr_push(&nlr) == 0) { + #endif + for (;;) { + if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { + if (pyexec_raw_repl() != 0) { + break; + } + } else { + if (pyexec_friendly_repl() != 0) { + break; + } + } + } + #if MICROPY_PY_SOFT_RESET + nlr_pop(); + } else { + mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); + } + #endif + } + +soft_reset_exit: + + #if MICROPY_PY_THREAD + mp_thread_deinit(); + #endif + + gc_sweep_all(); + + mp_hal_stdout_tx_str("MPY: soft reboot\r\n"); + #if MICROPY_ENABLE_CALLBACK_DEAL + qpy_callback_deal_deinit(); + qpy_callback_para_link_free_all(); + #endif + mp_deinit(); +#if !defined(PLAT_RDA) + fflush(stdout); +#endif + goto soft_reset; +} + +#if !MICROPY_VFS +mp_lexer_t *mp_lexer_new_from_file(qstr filename) { + mp_raise_OSError(MP_ENOENT); +} + +mp_import_stat_t mp_import_stat(const char *path) { + (void)path; + return MP_IMPORT_STAT_NO_EXIST; +} + +mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open); + +#endif + +application_init(quecpython_task, "quecpython_task", (MP_TASK_STACK_SIZE)/1024, 0); diff --git a/ports/quectel/misc_adc.c b/ports/quectel/misc_adc.c new file mode 100644 index 0000000000000..7f867498ab7f6 --- /dev/null +++ b/ports/quectel/misc_adc.c @@ -0,0 +1,119 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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 "stdio.h" +#include "stdlib.h" +#include +#include "py/obj.h" +#include "py/runtime.h" +#include "mphalport.h" + +#if MICROPY_QPY_MISC_ADC + +#include "helios_adc.h" + +typedef enum +{ + ADC0 = 0, + ADC1 = 1, + ADC2 = 2, + ADC3 = 3, +}ADCn; + +typedef struct _misc_adc_obj_t { + mp_obj_base_t base; + unsigned int pin; +} misc_adc_obj_t; + +const mp_obj_type_t misc_adc_type; + +static mp_obj_t Helios_adc_init(mp_obj_t self_in) +{ + int ret = Helios_ADC_Init(); + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_1(Helios_adc_init_obj, Helios_adc_init); + +static mp_obj_t Helios_adc_read(mp_obj_t self_in, mp_obj_t adc_channel) +{ + int ret = -1; + int channel = mp_obj_get_int(adc_channel); + if ((channel == 0) || (channel == 1) || (channel == 2) || (channel == 3)) + { + unsigned int chl = channel; + //ret = ql_adc_read(chl, &batvol); + + ret = Helios_ADC_Read((Helios_ADCNum) chl); + return mp_obj_new_int(ret); + } + return mp_obj_new_int(-1); +} +static MP_DEFINE_CONST_FUN_OBJ_2(Helios_adc_read_obj, Helios_adc_read); + +static mp_obj_t Helios_adc_deinit(mp_obj_t self_in) +{ + int ret = Helios_ADC_Deinit(); + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_1(Helios_adc_deinit_obj, Helios_adc_deinit); + + + +static const mp_rom_map_elem_t misc_adc_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&Helios_adc_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&Helios_adc_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&Helios_adc_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_ADC0), MP_ROM_INT(ADC0) }, +#if !defined(PLAT_Qualcomm) + { MP_ROM_QSTR(MP_QSTR_ADC1), MP_ROM_INT(ADC1) }, +#if !defined(PLAT_Unisoc_8850) && !defined(BOARD_EC600ECN_LC) && !defined(PLAT_SONY_ALT1350) + { MP_ROM_QSTR(MP_QSTR_ADC2), MP_ROM_INT(ADC2) }, + { MP_ROM_QSTR(MP_QSTR_ADC3), MP_ROM_INT(ADC3) }, +#endif +#endif +}; +static MP_DEFINE_CONST_DICT(misc_adc_locals_dict, misc_adc_locals_dict_table); + +static mp_obj_t misc_adc_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, MP_OBJ_FUN_ARGS_MAX, true); + + // create ADC object + misc_adc_obj_t *self = m_new_obj(misc_adc_obj_t); + self->base.type = &misc_adc_type; + return MP_OBJ_FROM_PTR(self); +} + +MP_DEFINE_CONST_OBJ_TYPE( + misc_adc_type, + MP_QSTR_ADC, + MP_TYPE_FLAG_NONE, + make_new, misc_adc_make_new, + locals_dict, &misc_adc_locals_dict + ); +#endif /* MICROPY_QPY_MISC_ADC */ + + diff --git a/ports/quectel/misc_power.c b/ports/quectel/misc_power.c new file mode 100644 index 0000000000000..93eafd8fcfc03 --- /dev/null +++ b/ports/quectel/misc_power.c @@ -0,0 +1,107 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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 "stdlib.h" +#include "mpconfigport.h" +#include "py/obj.h" +#include "py/compile.h" +#include "py/runtime.h" +#include "py/repl.h" +#include "py/mperrno.h" + +#if MICROPY_QPY_MISC_POWER + +#include "modmisc.h" +#include "helios_power.h" + +const mp_obj_type_t misc_power_type; + +static mp_obj_t misc_power_reset() +{ + int ret = 1; + Helios_Power_Reset(ret); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_0(misc_power_reset_obj, misc_power_reset); + + +static mp_obj_t misc_power_down() +{ + int ret = 1; + Helios_Power_Down(ret); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_0(misc_power_down_obj, misc_power_down); + +static mp_obj_t misc_power_get_down_reason() +{ + int ret; + ret = Helios_Power_GetDownReason(); + return mp_obj_new_int(ret); +} + +#if !defined(PLAT_RDA) +static MP_DEFINE_CONST_FUN_OBJ_0(misc_power_get_down_reason_obj, misc_power_get_down_reason); +#endif +static mp_obj_t misc_power_get_up_reason() +{ + int ret = 0; + ret = Helios_Power_GetUpReason(); + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_0(misc_power_get_up_reason_obj, misc_power_get_up_reason); + + +static mp_obj_t misc_power_get_batt() +{ + unsigned int ret; + ret = Helios_Power_GetBatteryVol(); + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_0(misc_power_get_batt_obj, misc_power_get_batt); + +static const mp_rom_map_elem_t misc_power_locals_dict_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_misc) }, + { MP_ROM_QSTR(MP_QSTR_powerRestart), MP_ROM_PTR(&misc_power_reset_obj) }, + { MP_ROM_QSTR(MP_QSTR_powerDown), MP_ROM_PTR(&misc_power_down_obj) }, + { MP_ROM_QSTR(MP_QSTR_powerOnReason), MP_ROM_PTR(&misc_power_get_up_reason_obj) }, +#if !defined(PLAT_RDA) + { MP_ROM_QSTR(MP_QSTR_powerDownReason), MP_ROM_PTR(&misc_power_get_down_reason_obj) }, +#endif + { MP_ROM_QSTR(MP_QSTR_getVbatt), MP_ROM_PTR(&misc_power_get_batt_obj) }, +}; + +static MP_DEFINE_CONST_DICT(misc_power_locals_dict, misc_power_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + misc_power_type, + MP_QSTR_Power, + MP_TYPE_FLAG_NONE, + locals_dict, &misc_power_locals_dict +); +#endif /* MICROPY_QPY_MISC_POWER */ diff --git a/ports/quectel/misc_pwm.c b/ports/quectel/misc_pwm.c new file mode 100644 index 0000000000000..bf592d1279a73 --- /dev/null +++ b/ports/quectel/misc_pwm.c @@ -0,0 +1,390 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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 "runtime.h" + +#if MICROPY_QPY_MISC_PWM + +#include "helios_pwm.h" +#include "helios_debug.h" + + +#define PWM_LOG(msg, ...) custom_log("pwm", msg, ##__VA_ARGS__) + + + +// Forward dec'l +const mp_obj_type_t misc_pwm_type; +const mp_obj_type_t misc_pwm_v2_type; + +typedef enum +{ + PWM_V1=0, + PWM_V2 +}pwm_type_t; + +typedef struct _misc_pwm_obj_t { + mp_obj_base_t base; + unsigned int pin; + unsigned int cycle_range; + unsigned short high_time; + unsigned short cycle_time; + unsigned char duty; + float frequency; + pwm_type_t type_pwm; +#if defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) + unsigned char pwm_en_sleep; +#endif +} misc_pwm_obj_t; + +typedef enum HELIOS_PWM_CYCLE_RANGE_ENUM +{ + HELIOS_PWM_CYCLE_ABOVE_1US, + HELIOS_PWM_CYCLE_ABOVE_1MS, + HELIOS_PWM_CYCLE_ABOVE_10US, + HELIOS_PWM_CYCLE_ABOVE_BELOW_US, +} HELIOS_PWM_CYCLE_RANGE_E; + +static misc_pwm_obj_t *misc_pwm_obj[PWMMAX] = {NULL}; + +static void misc_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + misc_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_printf(print, "PWM(pin:%u high time:%u cycle_time:%u)", self->pin, self->high_time, self->cycle_time); +} + + +typedef struct { + uint16_t Left_coordinate; + uint16_t Right_coordinata; +}Helios_PWM_range; + + +//helios_pwm[0]:1US +//helios_pwm[1]:1ms +//helios_pwm[2]:10us +//helios_pwm[3]:ns +#if defined(PLAT_ASR) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1602) +const Helios_PWM_range helios_pwm[4] = {{0, 157}, {0, 1023}, {1, 1575}, {0, 1024}}; + +#elif defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_ECR6600) || defined(PLAT_Unisoc_8850_R02) || defined(PLAT_Unisoc_8910_R06) +const Helios_PWM_range helios_pwm[4] = {{0, 10000}, {0, 10}, {1, 10000}, {99, 65535}}; +#elif defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) +#elif defined(PLAT_EIGEN) +#elif defined(PLAT_Qualcomm) +#elif defined(PLAT_SONY_ALT1350) + +#else +#error "Please check whether the platform supports PWM" +#endif + + +#if !defined(PLAT_ASR_1803s) && !defined(PLAT_ASR_1803sc) && !defined(PLAT_EIGEN) && !defined(PLAT_Qualcomm) && !defined(PLAT_SONY_ALT1350) +static int check_pwm_para(uint16_t cycle_range, uint16_t cycle_time, uint16_t hight_time) { + + if(cycle_range > HELIOS_PWM_CYCLE_ABOVE_BELOW_US || + hight_time <= helios_pwm[cycle_range].Left_coordinate || hight_time > helios_pwm[cycle_range].Right_coordinata || + cycle_time <= helios_pwm[cycle_range].Left_coordinate || cycle_time > helios_pwm[cycle_range].Right_coordinata || + hight_time > cycle_time) { + return -1; + } + return 0; +} +#endif +static void misc_pwm_init_helper(misc_pwm_obj_t *self, + size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_cycle_range, ARG_high_time, ARG_cycle_time }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_cycle_range, MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_high_time, MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_cycle_time, MP_ARG_INT, {.u_int = 0} }, +#if defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) + { MP_QSTR_pwm_en_sleep, MP_ARG_INT, {.u_int = 0} }, +#endif + }; + 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); + + //PWM_LOG("cycle_range=%d, high_time=%d, cycle_time=%d\n",args[ARG_cycle_range].u_int, args[ARG_high_time].u_int, args[ARG_cycle_time].u_int); +#if !(defined(PLAT_ASR) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) \ + || defined(PLAT_EIGEN) || defined(PLAT_Qualcomm) || defined(PLAT_ECR6600) || defined(PLAT_ASR_1602) || defined(PLAT_SONY_ALT1350)) + if(-1 == check_pwm_para(args[ARG_cycle_range].u_int, args[ARG_cycle_time].u_int, args[ARG_high_time].u_int)) { + mp_raise_ValueError(MP_ERROR_TEXT("PWM parameter error, please refer to wiki instructions to correct the parameters")); + } +#endif + + self->cycle_range = args[ARG_cycle_range].u_int; + self->high_time = args[ARG_high_time].u_int; + self->cycle_time = args[ARG_cycle_time].u_int; + self->type_pwm = PWM_V1; + PWM_LOG("cycle_range=%d, high_time=%d, cycle_time=%d\n",self->cycle_range, self->high_time, self->cycle_time); + + if(Helios_PWM_Init(self->pin) != 0) { + mp_raise_ValueError(MP_ERROR_TEXT("fail")); + } + +#if defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) + Helios_PWM_En_Sleep(self->pin,args[3].u_int); + PWM_LOG("Helios_PWM_En_Sleep->%d\n",args[3].u_int); +#endif +} + +static mp_obj_t misc_pwm_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, 4, 5, true); + int pin_id = mp_obj_get_int(args[0]); + + PWM_LOG("n_args = %d\n",n_args); + + if ((pin_id < 0) || (pin_id > PWMMAX-1)) + { + mp_raise_ValueError(MP_ERROR_TEXT("invalid PWMn value, must be in {0~3}.")); + } + + // create PWM object from the given pin + if (misc_pwm_obj[pin_id] == NULL) + { + misc_pwm_obj[pin_id] = mp_obj_malloc_with_finaliser(misc_pwm_obj_t, &misc_pwm_type); + } + misc_pwm_obj_t *self = misc_pwm_obj[pin_id]; + self->base.type = &misc_pwm_type; + self->pin = pin_id; + + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + misc_pwm_init_helper(self, n_args - 1, args + 1, &kw_args); + + return MP_OBJ_FROM_PTR(self); +} + +static mp_obj_t misc_pwm_init(size_t n_args, + const mp_obj_t *args, mp_map_t *kw_args) { + misc_pwm_init_helper(args[0], n_args - 1, args + 1, kw_args); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(misc_pwm_init_obj, 1, misc_pwm_init); + +//pwm v2 init by pass duty and frequency 20220624 @jimmy +static void misc_pwm_v2_init_helper(misc_pwm_obj_t *self, + size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + enum {ARG_frequency,ARG_duty}; + static const mp_arg_t allowed_args[] = + { + { MP_QSTR_frequency, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_duty, MP_ARG_INT, {.u_int = 0} }, +#if defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) + { MP_QSTR_pwm_en_sleep, MP_ARG_INT, {.u_int = 0} }, +#endif + }; + + 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(mp_obj_is_float(args[ARG_frequency].u_obj) == 0) + { + mp_raise_TypeError(MP_ERROR_TEXT("frequency type isn't float")); + } + if(args[ARG_duty].u_int > 100) + { + mp_raise_ValueError(MP_ERROR_TEXT("PWM parameter error,range duty should be 0~100")); + } + self->duty = args[ARG_duty].u_int; + self->frequency = mp_obj_float_get(args[ARG_frequency].u_obj); + self->type_pwm = PWM_V2; + + if(Helios_PWM_Init(self->pin) != 0) { + mp_raise_ValueError(MP_ERROR_TEXT("fail")); + } +#if defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) + Helios_PWM_En_Sleep(self->pin,args[2].u_int); + PWM_LOG("Helios_PWM_En_Sleep->%d\n",args[2].u_int); +#endif + +} +static mp_obj_t misc_pwm_v2_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, 3, 4, true); + int pin_id = mp_obj_get_int(args[0]); + + if ((pin_id < 0) || (pin_id > PWMMAX-1)) + { + mp_raise_ValueError(MP_ERROR_TEXT("invalid PWMn value, must be in {0~3}.")); + } + + // create PWM object from the given pin + if (misc_pwm_obj[pin_id] == NULL) + { + misc_pwm_obj[pin_id] = mp_obj_malloc_with_finaliser(misc_pwm_obj_t, &misc_pwm_type); + } + misc_pwm_obj_t *self = misc_pwm_obj[pin_id]; + self->base.type = &misc_pwm_v2_type; + self->pin = pin_id; + + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + misc_pwm_v2_init_helper(self, n_args - 1, args + 1, &kw_args); + + return MP_OBJ_FROM_PTR(self); +} + +static mp_obj_t misc_pwm_enable(size_t n_args, const mp_obj_t *args) +{ + misc_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]); + if(self->type_pwm == PWM_V1) + { + PWM_LOG("cycle_range=%d, high_time=%d, cycle_time=%d\n",self->cycle_range, self->high_time, self->cycle_time); + double frequency = 0; + float duty = 0; + if(n_args == 4) + { +#if !(defined(PLAT_ASR) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) \ + || defined(PLAT_EIGEN) || defined(PLAT_Qualcomm) || defined(PLAT_ECR6600) || defined(PLAT_ASR_1602) || defined(PLAT_SONY_ALT1350)) + if(-1 == check_pwm_para(mp_obj_get_int(args[1]), mp_obj_get_int(args[3]), mp_obj_get_int(args[2]))) + { + mp_raise_ValueError(MP_ERROR_TEXT("PWM parameter error, please refer to wiki instructions to correct the parameters")); + } +#endif + self->cycle_range = mp_obj_get_int(args[1]); + self->cycle_time = mp_obj_get_int(args[3]); + self->high_time = mp_obj_get_int(args[2]); + } + + if(self->cycle_range == HELIOS_PWM_CYCLE_ABOVE_1US || self->cycle_range == HELIOS_PWM_CYCLE_ABOVE_10US) + { + frequency = 1000000 /(double)self->cycle_time; + } + else if (self->cycle_range == HELIOS_PWM_CYCLE_ABOVE_1MS) + { + frequency = 1000 /(double)self->cycle_time; + } + else if(self->cycle_range == HELIOS_PWM_CYCLE_ABOVE_BELOW_US) + { + frequency = 1000000000 /(double)self->cycle_time; + } + duty = (float)self->high_time / (float)self->cycle_time; + + PWM_LOG("misc_pwm_enable = %lf %f\n",frequency, duty); + + int ret = Helios_PWM_Start(self->pin, frequency, duty); + + return mp_obj_new_int(ret); + } + else + { + if(n_args == 3) + { + if((mp_obj_get_int(args[2]) < 0) || (mp_obj_get_int(args[2]) > 100)) + { + mp_raise_ValueError(MP_ERROR_TEXT("PWM parameter error,range duty should be 0~100")); + } + if(mp_obj_is_float(args[1]) == 0) + { + mp_raise_TypeError(MP_ERROR_TEXT("frequency type isn't float")); + } + self->frequency = mp_obj_float_get(args[1]); + self->duty = mp_obj_get_int(args[2]); + } + PWM_LOG("duty=%d, frequency=%f\n",self->duty, self->frequency); + + int ret = Helios_PWM_Start(self->pin, self->frequency, (self->duty*1.0)/100); + + return mp_obj_new_int(ret); + } +} + +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(misc_pwm_enable_obj, 1, 4, misc_pwm_enable); + +static mp_obj_t misc_pwm_disable(mp_obj_t self_in) +{ + misc_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in); + + int ret = Helios_PWM_Stop(self->pin); + if (ret != 0) + { + ret = -1; + } + + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_1(misc_pwm_disable_obj, misc_pwm_disable); + +static mp_obj_t misc_pwm_deinit(mp_obj_t self_in) +{ + misc_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in); + + misc_pwm_obj[self->pin] = NULL; + + int ret = Helios_PWM_Deinit((Helios_PwnNum)self->pin); + if (ret != 0) + { + PWM_LOG("pwm%d deinit failed.\r\n", self->pin); + } + + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_1(misc_pwm_deinit_obj, misc_pwm_deinit); + +static const mp_rom_map_elem_t misc_pwm_locals_dict_table[] = { + // { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&misc_pwm_init_obj) }, + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&misc_pwm_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&misc_pwm_enable_obj) }, + { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&misc_pwm_disable_obj) }, + { MP_ROM_QSTR(MP_QSTR_ABOVE_1US), MP_ROM_INT(HELIOS_PWM_CYCLE_ABOVE_1US) }, + { MP_ROM_QSTR(MP_QSTR_ABOVE_MS), MP_ROM_INT(HELIOS_PWM_CYCLE_ABOVE_1MS) }, + { MP_ROM_QSTR(MP_QSTR_ABOVE_10US), MP_ROM_INT(HELIOS_PWM_CYCLE_ABOVE_10US) }, + { MP_ROM_QSTR(MP_QSTR_ABOVE_BELOW_US), MP_ROM_INT(HELIOS_PWM_CYCLE_ABOVE_BELOW_US) }, + { MP_ROM_QSTR(MP_QSTR_PWM0), MP_ROM_INT(PWM0) }, + #if !defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_Unisoc_8910_R06) || defined(PLAT_SONY_ALT1350) + PLAT_PWM_DEF(PLAT_PWM_NUMMAX), + #endif +}; + +static MP_DEFINE_CONST_DICT(misc_pwm_locals_dict, + misc_pwm_locals_dict_table); + + +MP_DEFINE_CONST_OBJ_TYPE( + misc_pwm_type, + MP_QSTR_PWM, + MP_TYPE_FLAG_NONE, + make_new, misc_pwm_make_new, + locals_dict, &misc_pwm_locals_dict + ); + +MP_DEFINE_CONST_OBJ_TYPE( + misc_pwm_v2_type, + MP_QSTR_PWM_V2, + MP_TYPE_FLAG_NONE, + make_new, misc_pwm_v2_make_new, + locals_dict, &misc_pwm_locals_dict + ); + +#endif /* MICROPY_QPY_MISC_PWM */ + diff --git a/ports/quectel/misc_usbnet.c b/ports/quectel/misc_usbnet.c new file mode 100644 index 0000000000000..24f61cc07b6f1 --- /dev/null +++ b/ports/quectel/misc_usbnet.c @@ -0,0 +1,213 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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 + +#include "mpconfigport.h" +#include "py/obj.h" +#include "py/compile.h" +#include "py/runtime.h" + +#if MICROPY_QPY_MISC_USBNET + +#include "helios_usbnet.h" +#include "helios_debug.h" + +#define HELIOS_MODUSB_LOG(msg, ...) custom_log("modusbnet", msg, ##__VA_ARGS__) + +STATIC mp_obj_t misc_usbnet_set_type(mp_obj_t type_in) +{ + int type = mp_obj_get_int(type_in); + if (type != HELIOS_USBNET_TYPE_ECM && type != HELIOS_USBNET_TYPE_RNDIS) + { + HELIOS_MODUSB_LOG("USBNET type must be Type_ECM or Type_RNDIS."); + return mp_obj_new_int(-1); + } + int ret = Helios_USBNET_SetType(type); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(misc_usbnet_set_type_obj, misc_usbnet_set_type); + +STATIC mp_obj_t misc_usbnet_get_type(void) +{ + Helios_USBNET_Type_e type = 0; + int ret = Helios_USBNET_GetType(&type); + if (ret == 0) + { + ret = type; + } + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(misc_usbnet_get_type_obj, misc_usbnet_get_type); + +STATIC mp_obj_t misc_usbnet_get_status(void) +{ + uint8_t status = 0; + int ret = Helios_USBNET_GetStatus(&status); + if (ret == 0) + { + ret = status; + } + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(misc_usbnet_get_status_obj, misc_usbnet_get_status); + +STATIC mp_obj_t misc_usbnet_open(void) +{ + int ret = Helios_USBNET_Open(); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(misc_usbnet_open_obj, misc_usbnet_open); + +STATIC mp_obj_t misc_usbnet_close(void) +{ + int ret = Helios_USBNET_Close(); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(misc_usbnet_close_obj, misc_usbnet_close); + +#if defined(PLAT_Unisoc) +STATIC mp_obj_t misc_usbnet_get_nat(size_t n_args, const mp_obj_t *args) +{ + if (n_args == 2) + { + uint8_t sim_id = mp_obj_get_int(args[0]); + uint8_t profile_id = mp_obj_get_int(args[1]); + if (sim_id != 0) + { + HELIOS_MODUSB_LOG("invalid value, now simId only supports 0."); + return mp_obj_new_int(-1); + } + if (profile_id < 1 || profile_id > 8) + { + HELIOS_MODUSB_LOG("invalid value, profileIdx should be in [1,8]."); + return mp_obj_new_int(-1); + } + int nat = Helios_USBNET_GetNat(sim_id, profile_id); + return mp_obj_new_int(nat); + } + return mp_obj_new_int(-1); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(misc_usbnet_get_nat_obj, 2, 2, misc_usbnet_get_nat); + +STATIC mp_obj_t misc_usbnet_set_nat(size_t n_args, const mp_obj_t *args) +{ + if (n_args == 3) + { + uint8_t sim_id = mp_obj_get_int(args[0]); + uint8_t profile_id = mp_obj_get_int(args[1]); + uint8_t nat = mp_obj_get_int(args[2]); + if (sim_id != 0) + { + HELIOS_MODUSB_LOG("invalid value, now simId only supports 0."); + return mp_obj_new_int(-1); + } + if (profile_id < 1 || profile_id > 8) + { + HELIOS_MODUSB_LOG("invalid value, profileIdx should be in [1,8]."); + return mp_obj_new_int(-1); + } + if (nat != 0 && nat != 1) + { + HELIOS_MODUSB_LOG("invalid value, Nat should be in [0,1]."); + return mp_obj_new_int(-1); + } + int ret = Helios_USBNET_SetNat(sim_id, profile_id, nat); + return mp_obj_new_int(ret); + } + return mp_obj_new_int(-1); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(misc_usbnet_set_nat_obj, 3, 3, misc_usbnet_set_nat); +#endif + +#if defined(PLAT_Unisoc_8850) +STATIC mp_obj_t misc_usbnet_set_MAC(mp_obj_t macinfo) +{ + mp_buffer_info_t m_macinfo; + unsigned char mac[6]; + mp_get_buffer_raise(macinfo, &m_macinfo, MP_BUFFER_READ); + if( m_macinfo.len != 6 ) { + HELIOS_MODUSB_LOG("mac length error"); + return mp_obj_new_int(-1); + } + memcpy(mac, m_macinfo.buf, 6); + + int ret = Helios_USBNET_SetMAC(mac); + + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(misc_usbnet_set_MAC_obj, misc_usbnet_set_MAC); + +STATIC mp_obj_t misc_usbnet_set_product(mp_obj_t macinfo) +{ + mp_buffer_info_t m_product; + char product[32]; + mp_get_buffer_raise(macinfo, &m_product, MP_BUFFER_READ); + if( m_product.len > 16 ) { + HELIOS_MODUSB_LOG("product length error"); + return mp_obj_new_int(-1); + } + memset(product, 0x00, sizeof(product)); + strncpy(product, m_product.buf, m_product.len); + + int ret = Helios_USBNET_SetProduct(product); + + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(misc_usbnet_set_product_obj, misc_usbnet_set_product); + +#endif + +STATIC const mp_rom_map_elem_t misc_usbnet_locals_dict_table[] = { + {MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_USBNET)}, + {MP_ROM_QSTR(MP_QSTR_set_worktype), MP_ROM_PTR(&misc_usbnet_set_type_obj)}, + {MP_ROM_QSTR(MP_QSTR_get_worktype), MP_ROM_PTR(&misc_usbnet_get_type_obj)}, + {MP_ROM_QSTR(MP_QSTR_get_status), MP_ROM_PTR(&misc_usbnet_get_status_obj)}, + {MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&misc_usbnet_open_obj)}, + {MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&misc_usbnet_close_obj)}, + {MP_ROM_QSTR(MP_QSTR_Type_ECM), MP_ROM_INT(HELIOS_USBNET_TYPE_ECM)}, + {MP_ROM_QSTR(MP_QSTR_Type_RNDIS), MP_ROM_INT(HELIOS_USBNET_TYPE_RNDIS)}, +#if defined(PLAT_Unisoc) + {MP_ROM_QSTR(MP_QSTR_getNat), MP_ROM_PTR(&misc_usbnet_get_nat_obj)}, + {MP_ROM_QSTR(MP_QSTR_setNat), MP_ROM_PTR(&misc_usbnet_set_nat_obj)}, +#endif +#if defined(PLAT_Unisoc_8850) + {MP_ROM_QSTR(MP_QSTR_setMAC), MP_ROM_PTR(&misc_usbnet_set_MAC_obj)}, + {MP_ROM_QSTR(MP_QSTR_setProduct), MP_ROM_PTR(&misc_usbnet_set_product_obj)}, +#endif +}; + +STATIC MP_DEFINE_CONST_DICT(misc_usbnet_locals_dict, misc_usbnet_locals_dict_table); + +const mp_obj_module_t misc_usbnet_module = { + .base = {&mp_type_module}, + .globals = (mp_obj_dict_t *)&misc_usbnet_locals_dict, +}; + +#endif /* MICROPY_QPY_MISC_USBNET */ diff --git a/ports/quectel/moddatacall.c b/ports/quectel/moddatacall.c new file mode 100644 index 0000000000000..8d264f170469c --- /dev/null +++ b/ports/quectel/moddatacall.c @@ -0,0 +1,833 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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 "nlr.h" +#include "objlist.h" +#include "objstr.h" +#include "runtime.h" +#include "mperrno.h" + +#if MICROPY_QPY_MODULE_DATACALL + +#include "helios_debug.h" +#include "helios_datacall.h" +#include "callbackdeal.h" + +#if MICROPY_QPY_MODULE_WANINFO +#include "netif.h" +#include "ip6_addr.h" +#endif + +#define MOD_DATACALL_LOG(msg, ...) custom_log(DataCall, msg, ##__VA_ARGS__) + +extern int _get_current_simid(void); + +static mp_obj_t qpy_datacall_set_pdp_context(size_t n_args, const mp_obj_t *args) +{ + int ret = 0; + int profile_id = mp_obj_get_int(args[0]); + int ip_type = mp_obj_get_int(args[1]); + int auth_type = mp_obj_get_int(args[5]); + + mp_buffer_info_t apninfo = {0}; + mp_buffer_info_t usrinfo = {0}; + mp_buffer_info_t pwdinfo = {0}; + mp_get_buffer_raise(args[2], &apninfo, MP_BUFFER_READ); + mp_get_buffer_raise(args[3], &usrinfo, MP_BUFFER_READ); + mp_get_buffer_raise(args[4], &pwdinfo, MP_BUFFER_READ); + + int min_profile_id = (int)Helios_DataCall_GetProfileIdxMin(); + int max_profile_id = (int)Helios_DataCall_GetProfileIdxMax(); + + if ((profile_id < min_profile_id) || (profile_id > max_profile_id)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, profileID should be in [%d,%d]."), min_profile_id, max_profile_id); + } + if ((ip_type < 0) || (ip_type > HELIOS_PDP_TYPE_NUM - 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, ipType should be in [0~%d]."), HELIOS_PDP_TYPE_NUM - 1); + } + if ((auth_type < 0) || (auth_type > HELIOS_AUTH_TYPE_NUM - 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, authType should be in [0~%d]."), HELIOS_AUTH_TYPE_NUM - 1); + } + if (apninfo.len > HELIOS_APN_LEN_MAX) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, the length of apn should be no more than [%d] bytes."), HELIOS_APN_LEN_MAX); + } + if (usrinfo.len > HELIOS_USR_LEN_MAX) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, the length of username should be no more than [%d] bytes."), HELIOS_USR_LEN_MAX); + } + if (pwdinfo.len > HELIOS_PWD_LEN_MAX) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, the length of password should be no more than [%d] bytes."), HELIOS_PWD_LEN_MAX); + } + if (usrinfo.len == 0 && pwdinfo.len == 0 && auth_type != 0) { + auth_type = 0; + } + + int cur_simid = _get_current_simid(); + if (n_args ==7) { + cur_simid = mp_obj_get_int(args[6]); + } + if ((cur_simid != 0) && (cur_simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); + } + + Helios_DataCallStartStruct pdp_context = {0}; + pdp_context.ip_type = ip_type; + pdp_context.auth = auth_type; + memcpy((void *)pdp_context.apn, apninfo.buf, apninfo.len); + memcpy((void *)pdp_context.user, usrinfo.buf, usrinfo.len); + memcpy((void *)pdp_context.pwd, pwdinfo.buf, pwdinfo.len); + MP_THREAD_GIL_EXIT(); + #if MICROPY_QPY_MODULE_DSDS + ret = Helios_DataCall_SetPDPContext(cur_simid,profile_id, &pdp_context); + #else + ret = Helios_DataCall_SetPDPContext(profile_id, &pdp_context); + #endif + MP_THREAD_GIL_ENTER(); + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_datacall_set_pdp_context_obj, 6, 7, qpy_datacall_set_pdp_context); + + +static mp_obj_t qpy_datacall_get_pdp_context(size_t n_args, const mp_obj_t *args) +{ + int ret = 0; + int profile_id = mp_obj_get_int(args[0]); + Helios_DataCallStartStruct pdp_context = {0}; + + int min_profile_id = (int)Helios_DataCall_GetProfileIdxMin(); + int max_profile_id = (int)Helios_DataCall_GetProfileIdxMax(); + + if ((profile_id < min_profile_id) || (profile_id > max_profile_id)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, profileID should be in [%d,%d]."), min_profile_id, max_profile_id); + } + int cur_simid = _get_current_simid(); + if (n_args ==2) { + cur_simid = mp_obj_get_int(args[1]); + } + if ((cur_simid != 0) && (cur_simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); + } + MP_THREAD_GIL_EXIT(); + #if MICROPY_QPY_MODULE_DSDS + ret = Helios_DataCall_GetPDPContext(cur_simid,profile_id, &pdp_context); + #else + ret = Helios_DataCall_GetPDPContext(profile_id, &pdp_context); + #endif + MP_THREAD_GIL_ENTER(); + if (ret == 0) + { + mp_obj_t pdp_ctx[5] = + { + mp_obj_new_int(pdp_context.ip_type), + mp_obj_new_str(pdp_context.apn, strlen(pdp_context.apn)), + mp_obj_new_str(pdp_context.user, strlen(pdp_context.user)), + mp_obj_new_str(pdp_context.pwd, strlen(pdp_context.pwd)), + mp_obj_new_int(pdp_context.auth) + }; + return mp_obj_new_tuple(5, pdp_ctx); + } + + return mp_obj_new_int(-1); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_datacall_get_pdp_context_obj, 1, 2, qpy_datacall_get_pdp_context); + +/*=============================================================================*/ +/* FUNCTION: qpy_datacall_start */ +/*=============================================================================*/ +/*!@brief : set APN and datacall. + * @profile_idx [in] profile_idx, 1~HELIOS_PROFILE_IDX_MAX + * @ip_type [in] 0-IPV4, 1-IPV6, 2-IPV4 and IPV6 + * @apn_name [in] anp name + * @usr_name [in] user name + * @password [in] password + * @auth_type [in] auth_type, 0-None, 1-PAP, 2-CHAP + * @return : + * - 0--successful + * - -1--error + */ +/*=============================================================================*/ +static mp_obj_t qpy_datacall_start(size_t n_args, const mp_obj_t *args) +{ + int ret = 0; + int profile_id = mp_obj_get_int(args[0]); + int ip_type = mp_obj_get_int(args[1]); + int auth_type = mp_obj_get_int(args[5]); + + mp_buffer_info_t apninfo = {0}; + mp_buffer_info_t usrinfo = {0}; + mp_buffer_info_t pwdinfo = {0}; + mp_get_buffer_raise(args[2], &apninfo, MP_BUFFER_READ); + mp_get_buffer_raise(args[3], &usrinfo, MP_BUFFER_READ); + mp_get_buffer_raise(args[4], &pwdinfo, MP_BUFFER_READ); + + int min_profile_id = (int)HELIOS_PROFILE_IDX_MIN; + int max_profile_id = (int)HELIOS_PROFILE_IDX_MAX; + + if ((profile_id < min_profile_id) || (profile_id > max_profile_id)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, profileID should be in [%d,%d]."), min_profile_id, max_profile_id); + } + if ((ip_type < 0) || (ip_type > HELIOS_PDP_TYPE_NUM - 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, ipType should be in [0~%d]."), HELIOS_PDP_TYPE_NUM - 1); + } + if ((auth_type < 0) || (auth_type > HELIOS_AUTH_TYPE_NUM - 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, authType should be in [0~%d]."), HELIOS_AUTH_TYPE_NUM - 1); + } + if (apninfo.len > HELIOS_APN_LEN_MAX) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, the length of apn should be no more than [%d] bytes."), HELIOS_APN_LEN_MAX); + } + if (usrinfo.len > HELIOS_USR_LEN_MAX) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, the length of username should be no more than [%d] bytes."), HELIOS_USR_LEN_MAX); + } + if (pwdinfo.len > HELIOS_PWD_LEN_MAX) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, the length of password should be no more than [%d] bytes."), HELIOS_PWD_LEN_MAX); + } + + MOD_DATACALL_LOG("[datacall] profile_idx=%d, ip_version=%d, auth_type=%d\r\n", profile_id, ip_type, auth_type); + MOD_DATACALL_LOG("[datacall] anp_name=%s, usr_name=%s, password=%s\r\n", apninfo.buf, usrinfo.buf, pwdinfo.buf); + + Helios_DataCallStartStruct DataCallStartStruct = {0}; + DataCallStartStruct.ip_type = (int32_t)ip_type; + DataCallStartStruct.auth = (int32_t)auth_type; + snprintf(DataCallStartStruct.apn, sizeof(DataCallStartStruct.apn), "%s", (char *)apninfo.buf); + snprintf(DataCallStartStruct.user, sizeof(DataCallStartStruct.user), "%s", (char *)usrinfo.buf); + snprintf(DataCallStartStruct.pwd, sizeof(DataCallStartStruct.pwd), "%s", (char *)pwdinfo.buf); + + int cur_simid = _get_current_simid(); + if (n_args ==7) { + cur_simid = mp_obj_get_int(args[6]); + } + if ((cur_simid != 0) && (cur_simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); + } + + MP_THREAD_GIL_EXIT(); + ret = Helios_DataCall_Start(profile_id, cur_simid, &DataCallStartStruct); + MP_THREAD_GIL_ENTER(); + + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_datacall_start_obj, 5, 7, qpy_datacall_start); + + +static mp_obj_t qpy_datacall_stop(size_t n_args, const mp_obj_t *args) +{ + int ret = 0; + int profile_id = mp_obj_get_int(args[0]); + int ip_type = mp_obj_get_int(args[1]); + int cur_simid = _get_current_simid(); + + int min_profile_id = (int)HELIOS_PROFILE_IDX_MIN; + int max_profile_id = (int)HELIOS_PROFILE_IDX_MAX; + + if ((profile_id < min_profile_id) || (profile_id > max_profile_id)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, profileID should be in [%d,%d]."), min_profile_id, max_profile_id); + } + if ((ip_type < 0) || (ip_type > 2)) + { + mp_raise_ValueError(MP_ERROR_TEXT("invalid value, ipTpye should be in [0,2].")); + } + if (n_args ==3) { + cur_simid = mp_obj_get_int(args[2]); + } + if ((cur_simid != 0) && (cur_simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); + } + MP_THREAD_GIL_EXIT(); + ret = Helios_DataCall_Stop((int32_t)profile_id, cur_simid, (int32_t)ip_type); + MP_THREAD_GIL_ENTER(); + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_datacall_stop_obj, 2, 3, qpy_datacall_stop); + + +/*=============================================================================*/ +/* FUNCTION: qpy_datacall_set_autoconnect */ +/*=============================================================================*/ +/*!@brief : set auto connect + * @profile_idx [in] profile_idx, 1~7 + * @enable [in] 0-disable, 1-enable + * @return : + * - 0--successful + * - -1--error + */ +/*=============================================================================*/ +static mp_obj_t qpy_datacall_set_autoconnect(size_t n_args, const mp_obj_t *args) +{ + int ret = 0; + int profile_id = mp_obj_get_int(args[0]); + bool enable = mp_obj_is_true(args[1]); + + int min_profile_id = (int)HELIOS_PROFILE_IDX_MIN; + int max_profile_id = (int)HELIOS_PROFILE_IDX_MAX; + + if ((profile_id < min_profile_id) || (profile_id > max_profile_id)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, profileID should be in [%d,%d]."), min_profile_id, max_profile_id); + } + int cur_simid = _get_current_simid(); + if (n_args ==3) { + cur_simid = mp_obj_get_int(args[2]); + } + if ((cur_simid != 0) && (cur_simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); + } + ret = Helios_DataCall_SetAutoConnect((int32_t)profile_id, cur_simid, enable); + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_datacall_set_autoconnect_obj, 1, 3, qpy_datacall_set_autoconnect); + + +/*=============================================================================*/ +/* FUNCTION: qpy_datacall_set_asynmode */ +/*=============================================================================*/ +/*!@brief : Set asynchronous mode to datacall + * @mode [in] 0-disable, 1-enable + * @return : + * - 0--successful + * - -1--error + */ +/*=============================================================================*/ +static mp_obj_t qpy_datacall_set_asynmode(mp_obj_t mode) +{ + bool enable = mp_obj_is_true(mode); + int cur_simid = _get_current_simid(); + Helios_DataCall_SetAsynMode((int32_t)Helios_DataCall_GetCurrentPDP(), cur_simid, enable); + return mp_obj_new_int(0); +} +static MP_DEFINE_CONST_FUN_OBJ_1(qpy_datacall_set_asynmode_obj, qpy_datacall_set_asynmode); + + +static mp_obj_t qpy_datacall_get_info(size_t n_args, const mp_obj_t *args) +{ + int ret = 0; + int profile_id = mp_obj_get_int(args[0]); + int ip_type = mp_obj_get_int(args[1]); + char ip4_ip_addr[16] = {0}; + char ip4_pri_dns[16] = {0}; + char ip4_sec_dns[16] = {0}; + char ip6_ip_addr[64] = {0}; + char ip6_pri_dns[64] = {0}; + char ip6_sec_dns[64] = {0}; + Helios_DataCallInfoStruct info = {0}; + int min_profile_id = (int)HELIOS_PROFILE_IDX_MIN; + int max_profile_id = (int)HELIOS_PROFILE_IDX_MAX; + + if ((profile_id < min_profile_id) || (profile_id > max_profile_id)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, profileID should be in [%d,%d]."), min_profile_id, max_profile_id); + } + if ((ip_type < 0) || (ip_type > HELIOS_PDP_TYPE_NUM - 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, ipType should be in [0~%d]."), HELIOS_PDP_TYPE_NUM - 1); + } + info.ip_version = ip_type; + int cur_simid = _get_current_simid(); + if (n_args ==3) { + cur_simid = mp_obj_get_int(args[2]); + } + if ((cur_simid != 0) && (cur_simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); + } + MP_THREAD_GIL_EXIT(); + ret = Helios_DataCall_GetInfo(profile_id, cur_simid, &info); + MP_THREAD_GIL_ENTER(); + if (0 == ret) + { + inet_ntop(AF_INET, &info.v4.addr.ip, ip4_ip_addr, sizeof(ip4_ip_addr)); + inet_ntop(AF_INET, &info.v4.addr.pri_dns, ip4_pri_dns, sizeof(ip4_pri_dns)); + inet_ntop(AF_INET, &info.v4.addr.sec_dns, ip4_sec_dns, sizeof(ip4_sec_dns)); + inet_ntop(AF_INET6, &info.v6.addr.ip, ip6_ip_addr, sizeof(ip6_ip_addr)); + inet_ntop(AF_INET6, &info.v6.addr.pri_dns, ip6_pri_dns, sizeof(ip6_pri_dns)); + inet_ntop(AF_INET6, &info.v6.addr.sec_dns, ip6_sec_dns, sizeof(ip6_sec_dns)); + + mp_obj_t ip4_list[5] = { + mp_obj_new_int(info.v4.state), + mp_obj_new_int(info.v4.reconnect), + + mp_obj_new_str(ip4_ip_addr, strlen(ip4_ip_addr)), + mp_obj_new_str(ip4_pri_dns, strlen(ip4_pri_dns)), + mp_obj_new_str(ip4_sec_dns, strlen(ip4_sec_dns)), + }; + mp_obj_t ip6_list[5] = { + mp_obj_new_int(info.v6.state), + mp_obj_new_int(info.v6.reconnect), + + mp_obj_new_str(ip6_ip_addr, strlen(ip6_ip_addr)), + mp_obj_new_str(ip6_pri_dns, strlen(ip6_pri_dns)), + mp_obj_new_str(ip6_sec_dns, strlen(ip6_sec_dns)), + }; + + if (ip_type == 0) + { + mp_obj_t tuple[3] = { + mp_obj_new_int(info.profile_idx), + mp_obj_new_int(info.ip_version), + mp_obj_new_list(5, ip4_list), + }; + return mp_obj_new_tuple(3, tuple); + } + else if (ip_type == 1) + { + mp_obj_t tuple[3] = { + mp_obj_new_int(info.profile_idx), + mp_obj_new_int(info.ip_version), + mp_obj_new_list(5, ip6_list), + }; + return mp_obj_new_tuple(3, tuple); + } + else if (ip_type == 2) + { + mp_obj_t tuple[4] = { + mp_obj_new_int(info.profile_idx), + mp_obj_new_int(info.ip_version), + mp_obj_new_list(5, ip4_list), + mp_obj_new_list(5, ip6_list), + }; + + return mp_obj_new_tuple(4, tuple); + } + } + return mp_obj_new_int(ret); +} + +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_datacall_get_info_obj, 1, 3, qpy_datacall_get_info); + + + +static c_callback_t * g_usr_callback = NULL; + +static void datacall_callback(int32_t profile_idx, uint8_t sim_id, int32_t nw_status) +{ + + MOD_DATACALL_LOG("[datacall] pdp = %d, nwsta = %d\r\n", profile_idx, nw_status); + if (g_usr_callback) + { + st_CallBack_Datacall *Datacall_param = (st_CallBack_Datacall *)malloc(sizeof(st_CallBack_Datacall)); + if(NULL != Datacall_param) + { + Datacall_param->profile_idx = profile_idx; + Datacall_param->nw_status = nw_status; + Datacall_param->sim_id = sim_id; + Datacall_param->callback = *g_usr_callback; + + qpy_send_msg_to_callback_deal_thread(CALLBACK_TYPE_ID_DATACALL, Datacall_param); + } + } +} + + +/*=============================================================================*/ +/* FUNCTION: qpy_datacall_register_usr_callback */ +/*=============================================================================*/ +/*!@brief : register the callback function for user + * @user_cb [in] callback function + * @return : + * - 0--successful + * - -1--error + */ +/*=============================================================================*/ +static mp_obj_t qpy_datacall_register_usr_callback(mp_obj_t callback) +{ + static c_callback_t cb = {0}; + memset(&cb, 0, sizeof(c_callback_t)); + cb.arg = mp_obj_new_tuple(3, NULL); + g_usr_callback = &cb; + mp_sched_schedule_callback_register(g_usr_callback, callback); + + Helios_DataCallInitStruct DataCallInitStruct = {datacall_callback}; + int cur_simid = _get_current_simid(); + Helios_DataCall_Init((int32_t)Helios_DataCall_GetCurrentPDP(), cur_simid, &DataCallInitStruct); + return mp_obj_new_int(0); +} +static MP_DEFINE_CONST_FUN_OBJ_1(qpy_register_usr_callback_obj, qpy_datacall_register_usr_callback); + +static mp_obj_t qpy_datacall_get_pdp_range(void) +{ + uint32_t min = Helios_DataCall_GetProfileIdxMin(); + uint32_t max = Helios_DataCall_GetProfileIdxMax(); + mp_obj_t tuple[2] = + { + mp_obj_new_int(min), + mp_obj_new_int(max) + }; + + return mp_obj_new_tuple(2, tuple); +} +static MP_DEFINE_CONST_FUN_OBJ_0(qpy_get_pdp_range_obj, qpy_datacall_get_pdp_range); + +static mp_obj_t qpy_datacall_get_range(mp_obj_t kind) +{ + int para_kind = mp_obj_get_int(kind); + + if (para_kind == 0) //apn + { + return mp_obj_new_int(HELIOS_APN_LEN_MAX); + } + else if (para_kind == 1) //password + { + return mp_obj_new_int(HELIOS_PWD_LEN_MAX); + } + else if (para_kind == 2) //usrname + { + return mp_obj_new_int(HELIOS_USR_LEN_MAX); + } + else if (para_kind == 3) //pid + { + return mp_obj_new_int(HELIOS_PROFILE_IDX_MAX); + } + else if (para_kind == 4) //iptype + { + return mp_obj_new_int(HELIOS_PDP_TYPE_NUM); + } + else if (para_kind == 5) //authtype + { + return mp_obj_new_int(HELIOS_AUTH_TYPE_NUM); + } + else + { + return mp_obj_new_int(-1); + } +} +static MP_DEFINE_CONST_FUN_OBJ_1(qpy_datacall_get_range_obj, qpy_datacall_get_range); + +static mp_obj_t qpy_datacall_get_apn(size_t n_args, const mp_obj_t *args) +{ +#if defined(PLAT_ASR) || defined(PLAT_Unisoc) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc)|| defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) \ + || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_ASR_1602) || defined(PLAT_Unisoc_8910_R06) + int sim_id = mp_obj_get_int(args[0]); + int ret = 0; + char apn[99+1] = {0}; + if (sim_id != 0) + { + mp_raise_ValueError(MP_ERROR_TEXT("invalid simid.")); + } + if (n_args == 1) + { + MP_THREAD_GIL_EXIT(); + ret = Helios_DataCall_GetApn(2, sim_id, apn); + MP_THREAD_GIL_ENTER(); + if (ret == 0) + { + return mp_obj_new_str(apn, strlen(apn)); + } + return mp_obj_new_int(-1); + } + else if (n_args == 2) + { + int pid = mp_obj_get_int(args[1]); + MP_THREAD_GIL_EXIT(); + ret = Helios_DataCall_GetApn(3, sim_id, apn, pid); + MP_THREAD_GIL_ENTER(); + if (ret == 0) + { + return mp_obj_new_str(apn, strlen(apn)); + } + return mp_obj_new_int(-1); + } + else + { + mp_raise_ValueError(MP_ERROR_TEXT("invalid value, The number of parameters cannot be greater than 2.")); + } +#else + mp_raise_ValueError(MP_ERROR_TEXT("NOT SUPPORT")); +#endif +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_datacall_get_apn_obj, 1, 2, qpy_datacall_get_apn); + +#if defined(PLAT_ASR) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_Unisoc_8910_R06) +static mp_obj_t qpy_datacall_set_dns_server(size_t n_args, const mp_obj_t *args) +{ + int profile_id = mp_obj_get_int(args[0]); + int sim_id = mp_obj_get_int(args[1]); + + mp_buffer_info_t new_pri_dns = {0}; + mp_buffer_info_t new_sec_dns = {0}; + mp_get_buffer_raise(args[2], &new_pri_dns, MP_BUFFER_READ); + mp_get_buffer_raise(args[3], &new_sec_dns, MP_BUFFER_READ); + + int min_profile_id = (int)HELIOS_PROFILE_IDX_MIN; + int max_profile_id = (int)HELIOS_PROFILE_IDX_MAX; + + if ((profile_id < min_profile_id) || (profile_id > max_profile_id)) + { + mp_raise_msg_varg(&mp_type_ValueError, "invalid value, profileID should be in [%d,%d].", min_profile_id, max_profile_id); + } + + char new_pri[128]; + char new_sec[128]; + memset(&new_pri, 0, sizeof(new_pri)); + memset(&new_sec, 0, sizeof(new_sec)); + + memcpy(new_pri, new_pri_dns.buf, new_pri_dns.len); + memcpy(new_sec, new_sec_dns.buf, new_sec_dns.len); + + int ret = 0; + MP_THREAD_GIL_EXIT(); + ret = Helios_DataCall_SetDnsServer(profile_id, sim_id, new_pri, new_sec); + MP_THREAD_GIL_ENTER(); + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_datacall_set_dns_server_obj, 4, 4, qpy_datacall_set_dns_server); +#endif + +static mp_obj_t qpy_datacall_get_date_speed(size_t n_args, const mp_obj_t *args) +{ + uint32_t rx = 0, tx = 0; +#if defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) + MP_THREAD_GIL_EXIT(); + Helios_DataCall_GetDataSpeed(&rx, &tx); + MP_THREAD_GIL_ENTER(); +#endif + mp_obj_t date_speed[2] = { + mp_obj_new_int_from_uint(rx), //bps + mp_obj_new_int_from_uint(tx), //bps + }; + return mp_obj_new_tuple(2,date_speed); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_datacall_get_date_speed_obj, 0, 0, qpy_datacall_get_date_speed); + +static mp_obj_t qpy_datacall_get_address_info(size_t n_args, const mp_obj_t *args) +{ + int profile_id = mp_obj_get_int(args[0]); + int ip_type = 0; + + if (n_args == 2) + { + ip_type = mp_obj_get_int(args[1]); + } + +#if MICROPY_QPY_MODULE_WANINFO + struct netif* netif_cfg = netif_get_by_cid(profile_id-1); + + if(netif_cfg) + { + static uint8_t g_mac[6] = {0}; + g_mac[0] = netif_cfg->hwaddr[0]; + g_mac[1] = netif_cfg->hwaddr[1]; + g_mac[2] = netif_cfg->hwaddr[2]; + g_mac[3] = netif_cfg->hwaddr[3]; + g_mac[4] = netif_cfg->hwaddr[4]; + g_mac[5] = netif_cfg->hwaddr[5]; + + char mac[64] = {0}; + sprintf(mac, "%02X-%02X-%02X-%02X-%02X-%02X", g_mac[0], g_mac[1], g_mac[2], g_mac[3], g_mac[4], g_mac[5]); + + if (ip_type == 0)//IPV4 + { + char mask[16] = {0}; + char gw[16] = {0}; + + struct sockaddr_in local_v4; + + local_v4.sin_addr.s_addr = netif_cfg->netmask.addr; + inet_ntop(AF_INET, &local_v4.sin_addr.s_addr, mask, sizeof(mask)); + + local_v4.sin_addr.s_addr = netif_cfg->gw.addr; + inet_ntop(AF_INET, &local_v4.sin_addr.s_addr, gw, sizeof(gw)); + + mp_obj_t addrinfo_tuple[3] = { + mp_obj_new_str(mac, strlen(mac)), + mp_obj_new_str(mask, strlen(mask)), + mp_obj_new_str(gw, strlen(gw)) + }; + + return mp_obj_new_tuple(3,addrinfo_tuple); + } + else if (ip_type == 1)//IPV6 + { + struct sockaddr_in6 local_v6; + char ip6_gw[64] = {0}; + ip6_addr_t * ip6_addr_ptr = NULL; + + ip6_addr_ptr = &(netif_cfg->ip6_gw); + memcpy(&local_v6.sin6_addr, ip6_addr_ptr, sizeof(ip6_addr_t)); + inet_ntop(AF_INET6, &local_v6.sin6_addr, ip6_gw, sizeof(ip6_gw)); + + mp_obj_t addrinfo_tuple[2] = { + mp_obj_new_str(mac, strlen(mac)), + mp_obj_new_str(ip6_gw, strlen(ip6_gw)) + }; + + return mp_obj_new_tuple(2,addrinfo_tuple); + } + else if (ip_type == 2)//IPV4&6 + { + char mask[16] = {0}; + char gw[16] = {0}; + + struct sockaddr_in local_v4; + + local_v4.sin_addr.s_addr = netif_cfg->netmask.addr; + inet_ntop(AF_INET, &local_v4.sin_addr.s_addr, mask, sizeof(mask)); + + local_v4.sin_addr.s_addr = netif_cfg->gw.addr; + inet_ntop(AF_INET, &local_v4.sin_addr.s_addr, gw, sizeof(gw)); + + mp_obj_t addrinfo_tuple[3] = { + mp_obj_new_str(mac, strlen(mac)), + mp_obj_new_str(mask, strlen(mask)), + mp_obj_new_str(gw, strlen(gw)) + }; + + char ip6_gw[64] = {0}; + struct sockaddr_in6 local_v6; + ip6_addr_t * ip6_addr_ptr = NULL; + + ip6_addr_ptr = &(netif_cfg->ip6_gw); + memcpy(&local_v6.sin6_addr, ip6_addr_ptr, sizeof(ip6_addr_t)); + inet_ntop(AF_INET6, &local_v6.sin6_addr, ip6_gw, sizeof(ip6_gw)); + + mp_obj_t addr6info_tuple[2] = { + mp_obj_new_str(mac, strlen(mac)), + mp_obj_new_str(ip6_gw, strlen(ip6_gw)) + }; + + mp_obj_t ipconfig_list[2] = { + mp_obj_new_tuple(3, addrinfo_tuple), + mp_obj_new_tuple(2, addr6info_tuple) + }; + return mp_obj_new_list(2, ipconfig_list); + } + } +#else + (void)profile_id;(void)ip_type; +#endif + + return mp_obj_new_int(-1); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_datacall_get_address_info_obj, 1, 2, qpy_datacall_get_address_info); + +static mp_obj_t qpy_datacall_get_sim_info(size_t n_args, const mp_obj_t *args) +{ +#if MICROPY_QPY_MODULE_WANINFO + int sim_id = mp_obj_get_int(args[0]); + Helios_DataCallSimUsed info; + + Helios_DataCall_GetSimUsed(sim_id, &info); + + mp_obj_t siminfo_tuple[4] = { + mp_obj_new_int(info.recv_MBytes_sim), + mp_obj_new_int(info.recv_Bytes_sim), + mp_obj_new_int(info.used_MBytes_sim), + mp_obj_new_int(info.used_Bytes_sim) + }; + + return mp_obj_new_tuple(4,siminfo_tuple); +#endif + + return mp_obj_new_int(-1); +}static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_datacall_get_sim_info_obj, 1, 1, qpy_datacall_get_sim_info); + +static mp_obj_t qpy_module_datacall_deinit(void) +{ + g_usr_callback = NULL; + MOD_DATACALL_LOG("module datacall deinit.\r\n"); +#if defined(PLAT_ASR) || defined(PLAT_Unisoc) || defined(PLAT_Qualcomm) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_Unisoc_8910_R06) + Helios_DataCall_Deinit(); +#endif + return mp_obj_new_int(0); +} +static MP_DEFINE_CONST_FUN_OBJ_0(qpy_module_datacall_deinit_obj, qpy_module_datacall_deinit); + + +static mp_obj_t qpy_datacall_use_attach_apn(size_t n_args, const mp_obj_t *args) +{ +#if defined(PLAT_ASR) + int ret = 0; + bool is_using_attach_apn = false; + if (n_args == 1) { + is_using_attach_apn = mp_obj_is_true(args[0]); + MP_THREAD_GIL_EXIT(); + ret = Helios_DataCall_SetIsUseAttachApn(is_using_attach_apn ? 0 : 1); + MP_THREAD_GIL_ENTER(); + return mp_obj_new_int(ret); + } else { + MP_THREAD_GIL_EXIT(); + is_using_attach_apn = Helios_DataCall_GetIsUseAttachApn(); + MP_THREAD_GIL_ENTER(); + return mp_obj_new_bool(!is_using_attach_apn); + } +#else + mp_raise_ValueError(MP_ERROR_TEXT("NOT SUPPORT")); +#endif +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_datacall_use_attach_apn_obj, 0, 1, qpy_datacall_use_attach_apn); + + +static const mp_rom_map_elem_t mp_module_datacall_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_dial) }, + { MP_ROM_QSTR(MP_QSTR___qpy_module_deinit__), MP_ROM_PTR(&qpy_module_datacall_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_setPDPContext), MP_ROM_PTR(&qpy_datacall_set_pdp_context_obj) }, + { MP_ROM_QSTR(MP_QSTR_getPDPContext), MP_ROM_PTR(&qpy_datacall_get_pdp_context_obj) }, + { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&qpy_datacall_start_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&qpy_datacall_stop_obj) }, + { MP_ROM_QSTR(MP_QSTR_setAutoConnect), MP_ROM_PTR(&qpy_datacall_set_autoconnect_obj) }, + { MP_ROM_QSTR(MP_QSTR_getInfo), MP_ROM_PTR(&qpy_datacall_get_info_obj) }, + { MP_ROM_QSTR(MP_QSTR_setCallback), MP_ROM_PTR(&qpy_register_usr_callback_obj) }, + { MP_ROM_QSTR(MP_QSTR_setAsynMode), MP_ROM_PTR(&qpy_datacall_set_asynmode_obj) }, + { MP_ROM_QSTR(MP_QSTR_getPdpRange), MP_ROM_PTR(&qpy_get_pdp_range_obj) }, + { MP_ROM_QSTR(MP_QSTR_getRange), MP_ROM_PTR(&qpy_datacall_get_range_obj) }, + { MP_ROM_QSTR(MP_QSTR_getApn), MP_ROM_PTR(&qpy_datacall_get_apn_obj) }, + #if defined(PLAT_ASR) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_Unisoc_8910_R06) + { MP_ROM_QSTR(MP_QSTR_setDnsserver), MP_ROM_PTR(&qpy_datacall_set_dns_server_obj) }, + #endif + { MP_ROM_QSTR(MP_QSTR_useAttachApn), MP_ROM_PTR(&qpy_datacall_use_attach_apn_obj) }, + { MP_ROM_QSTR(MP_QSTR_getSpeed), MP_ROM_PTR(&qpy_datacall_get_date_speed_obj) }, + { MP_ROM_QSTR(MP_QSTR_getAddressinfo), MP_ROM_PTR(&qpy_datacall_get_address_info_obj) }, + { MP_ROM_QSTR(MP_QSTR_getSiminfo), MP_ROM_PTR(&qpy_datacall_get_sim_info_obj) }, +}; +static MP_DEFINE_CONST_DICT(mp_module_datacall_globals, mp_module_datacall_globals_table); + + +const mp_obj_module_t mp_module_dial = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&mp_module_datacall_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_dial, mp_module_dial); +#endif /* MICROPY_QPY_MODULE_DATACALL */ diff --git a/ports/quectel/moddatacall.h b/ports/quectel/moddatacall.h new file mode 100644 index 0000000000000..880548c5d494f --- /dev/null +++ b/ports/quectel/moddatacall.h @@ -0,0 +1,42 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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 __MODDATACALL_H__ +#define __MODDATACALL_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void(* nw_status_cb)(int profile_idx, int nw_status); + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/ports/quectel/moddev.c b/ports/quectel/moddev.c new file mode 100644 index 0000000000000..aa62f787b5c40 --- /dev/null +++ b/ports/quectel/moddev.c @@ -0,0 +1,288 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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 "obj.h" +#include "runtime.h" +#include "mphalport.h" + +#if MICROPY_QPY_MODULE_MODEM + +#include "helios_dev.h" + + +static mp_obj_t queclib_dev_product_id() +{ + char product_id_str[64] = {0}; + int ret = Helios_Dev_GetPID((void *)product_id_str, sizeof(product_id_str)); + if(ret == 0) + { + return mp_obj_new_str(product_id_str, strlen(product_id_str)); + } + return mp_obj_new_int(-1); +} + +static MP_DEFINE_CONST_FUN_OBJ_0(queclib_dev_product_id_obj, queclib_dev_product_id); + +extern int _get_current_simid(void); + +static mp_obj_t queclib_dev_serial_number(size_t n_args, const mp_obj_t *args) +{ +#if !defined(PLAT_aic8800m40) && !defined(PLAT_ECR6600) && !defined(PLAT_SONY_ALT1350) + int cur_simid = _get_current_simid(); + if (n_args ==1) { + cur_simid = mp_obj_get_int(args[0]); + } + if ((cur_simid != 0) && (cur_simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); + } +#endif + char serial_number_str[64] = {0}; + #if MICROPY_QPY_MODULE_DSDS + int ret = Helios_Dev_GetSN((void *)serial_number_str, sizeof(serial_number_str), cur_simid); + #else + int ret = Helios_Dev_GetSN((void *)serial_number_str, sizeof(serial_number_str),0); + #endif + if(ret == 0) + { + return mp_obj_new_str(serial_number_str, strlen(serial_number_str)); + } + return mp_obj_new_int(-1); +} + +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(queclib_dev_serial_number_obj, 0, 1, queclib_dev_serial_number); + +static mp_obj_t queclib_dev_model() +{ + char model_str[64] = {0}; + int ret = Helios_Dev_GetModel((void *)model_str, sizeof(model_str)); + if(ret == 0) + { + return mp_obj_new_str(model_str, strlen(model_str)); + } + return mp_obj_new_int(-1); +} + +static MP_DEFINE_CONST_FUN_OBJ_0(queclib_dev_model_obj, queclib_dev_model); + + +mp_obj_t queclib_dev_fw_version() +{ + char fw_version_str[64] = {0}; + int ret = Helios_Dev_GetFwVersion((void *)fw_version_str, sizeof(fw_version_str)); + if(ret == 0) + { + return mp_obj_new_str(fw_version_str, strlen(fw_version_str)); + } + return mp_obj_new_int(-1); +} + +static MP_DEFINE_CONST_FUN_OBJ_0(queclib_dev_fw_version_obj, queclib_dev_fw_version); + + +#if !defined(PLAT_aic8800m40) && !defined(PLAT_ECR6600) + +static mp_obj_t queclib_dev_imei(size_t n_args, const mp_obj_t *args) +{ + #if !defined(PLAT_SONY_ALT1350) + int cur_simid = _get_current_simid(); + #else + int cur_simid = 0; + #endif + if (n_args ==1) { + cur_simid = mp_obj_get_int(args[0]); + } + if ((cur_simid != 0) && (cur_simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); + } + //the imei length is 15-17 bytes + char imei_str[19] = {0}; +#if MICROPY_QPY_MODULE_DSDS + int ret = Helios_Dev_GetIMEI((void *)imei_str, sizeof(imei_str), cur_simid); +#else + #if MICROPY_QPY_MODULE_DUALIMEI + cur_simid = (n_args ==1) ? cur_simid + 2 : 0; + int ret = Helios_Dev_GetIMEI((void *)imei_str, sizeof(imei_str),cur_simid); + #else + int ret = Helios_Dev_GetIMEI((void *)imei_str, sizeof(imei_str),0); + #endif +#endif + if(ret == 0) + { + return mp_obj_new_str(imei_str, strlen(imei_str)); + } + return mp_obj_new_int(-1); +} + +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(queclib_dev_imei_obj, 0, 1, queclib_dev_imei); +#endif + +#if defined (PLAT_Qualcomm) +static mp_obj_t queclib_dev_backup() +{ + MP_THREAD_GIL_EXIT(); + int ret = Helios_Dev_Backup(); + MP_THREAD_GIL_ENTER(); + if( ret != 0 ) return mp_obj_new_int(-1); + return mp_obj_new_int(0); +} + +static MP_DEFINE_CONST_FUN_OBJ_0(queclib_dev_backup_obj, queclib_dev_backup); + +static mp_obj_t queclib_dev_backup_status() +{ + Helios_DevBackupStatusStruct backup_status_info = {0}; + + int ret = Helios_Dev_Backup_Status(&backup_status_info); + if( ret == 0 ) + { + mp_obj_t info[3] = + { + mp_obj_new_int(backup_status_info.backup_valid), + mp_obj_new_int(backup_status_info.backup_cnt), + mp_obj_new_int(backup_status_info.restore_cnt), + }; + return mp_obj_new_tuple(3, info); + } + return mp_obj_new_int(-1); +} + +static MP_DEFINE_CONST_FUN_OBJ_0(queclib_dev_backup_status_obj, queclib_dev_backup_status); + +static mp_obj_t set_usbmode(mp_obj_t usbmode) { + int mode = mp_obj_get_int(usbmode); + extern int Helios_Dev_SetUSBMode(int mode); + return mp_obj_new_int(Helios_Dev_SetUSBMode(mode)); +} + +static MP_DEFINE_CONST_FUN_OBJ_1(set_usbmode_obj, set_usbmode); + +//forrest.liu@20220112 add for main uart change from AT to general uart +extern void Helios_Dev_Main_UART_Enable_Set(int onoff); +extern int Helios_Dev_Main_UART_Enable_Get(void); + +static mp_obj_t main_uart_enable_set(mp_obj_t onoff) { + int mode = mp_obj_get_int(onoff); + Helios_Dev_Main_UART_Enable_Set(mode); + return mp_obj_new_int(0); +} + +static MP_DEFINE_CONST_FUN_OBJ_1(main_uart_enable_set_obj, main_uart_enable_set); + +static mp_obj_t main_uart_enable_get() { + int mode = Helios_Dev_Main_UART_Enable_Get(); + return mp_obj_new_int(mode); +} + +static MP_DEFINE_CONST_FUN_OBJ_0(main_uart_enable_get_obj, main_uart_enable_get); + +#endif + +#if defined(PLAT_ECR6600) || defined(PLAT_aic8800m40) + +static mp_obj_t queclib_dev_mac() +{ + char serial_number_str[64] = {0}; + int ret = Helios_Dev_GetMAC((void *)serial_number_str, sizeof(serial_number_str)); + sprintf(serial_number_str,"%02x:%02x:%02x:%02x:%02x:%02x", + serial_number_str[0]&0xff, + serial_number_str[1]&0xff, + serial_number_str[2]&0xff, + serial_number_str[3]&0xff, + serial_number_str[4]&0xff, + serial_number_str[5]&0xff); + + if(ret == 0) + { + return mp_obj_new_str(serial_number_str, strlen(serial_number_str)); + } + + return mp_obj_new_int(-1); +} + +static MP_DEFINE_CONST_FUN_OBJ_0(queclib_dev_mac_obj, queclib_dev_mac); +#endif + + +#if defined(BOARD_EG915ULA_AC_USBUP) || defined(BOARD_EG915UCN_AC_USBUP) \ + || defined(BOARD_EG915UEU_AC_USBUP) || defined(BOARD_EG915UEC_AC_USBUP) +int Helios_Dev_SetIMEI(void *buffer); + +static mp_obj_t queclib_dev_imei_set(mp_obj_t imei) { + char *imei_str = (char *)mp_obj_str_get_str(imei); + MP_THREAD_GIL_EXIT(); + int ret = Helios_Dev_SetIMEI(imei_str); + MP_THREAD_GIL_ENTER(); + if(ret != 0) + { + return mp_obj_new_int(-1); + } + return mp_obj_new_int(0); +} + +static MP_DEFINE_CONST_FUN_OBJ_1(queclib_dev_imei_set_obj, queclib_dev_imei_set); +#endif + +static const mp_rom_map_elem_t mp_module_modem_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_modem) }, +#if !defined(PLAT_aic8800m40) + { MP_ROM_QSTR(MP_QSTR_getDevSN), MP_ROM_PTR(&queclib_dev_serial_number_obj) }, +#endif +#if !defined(PLAT_aic8800m40) && !defined(PLAT_ECR6600) + { MP_ROM_QSTR(MP_QSTR_getDevImei), MP_ROM_PTR(&queclib_dev_imei_obj) }, +#endif + { MP_ROM_QSTR(MP_QSTR_getDevModel), MP_ROM_PTR(&queclib_dev_model_obj) }, + { MP_ROM_QSTR(MP_QSTR_getDevFwVersion), MP_ROM_PTR(&queclib_dev_fw_version_obj) }, + { MP_ROM_QSTR(MP_QSTR_getDevProductId), MP_ROM_PTR(&queclib_dev_product_id_obj) }, + +#if defined (PLAT_Qualcomm) + { MP_ROM_QSTR(MP_QSTR_backup), MP_ROM_PTR(&queclib_dev_backup_obj) }, + { MP_ROM_QSTR(MP_QSTR_backupStatus), MP_ROM_PTR(&queclib_dev_backup_status_obj) }, + { MP_ROM_QSTR(MP_QSTR_setUSBMode), MP_ROM_PTR(&set_usbmode_obj) }, + { MP_ROM_QSTR(MP_QSTR_main_uart_enable_set), MP_ROM_PTR(&main_uart_enable_set_obj) }, + { MP_ROM_QSTR(MP_QSTR_main_uart_enable_get), MP_ROM_PTR(&main_uart_enable_get_obj) }, +#endif +#if defined(BOARD_EG915ULA_AC_USBUP) || defined(BOARD_EG915UCN_AC_USBUP) \ + || defined(BOARD_EG915UEU_AC_USBUP) || defined(BOARD_EG915UEC_AC_USBUP) + { MP_ROM_QSTR(MP_QSTR_setDevImei), MP_ROM_PTR(&queclib_dev_imei_set_obj) }, +#endif +#if defined(PLAT_ECR6600) || defined(PLAT_aic8800m40) + { MP_ROM_QSTR(MP_QSTR_getDevMAC), MP_ROM_PTR(&queclib_dev_mac_obj) }, +#endif +}; +static MP_DEFINE_CONST_DICT(mp_module_modem_globals, mp_module_modem_globals_table); + + +const mp_obj_module_t mp_module_modem = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&mp_module_modem_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_modem, mp_module_modem); +#endif /* MICROPY_PORT_BUILTIN_MODULES_MODEM */ diff --git a/ports/quectel/modexample.c b/ports/quectel/modexample.c new file mode 100644 index 0000000000000..ceb1400e72636 --- /dev/null +++ b/ports/quectel/modexample.c @@ -0,0 +1,127 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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 +#include "py/compile.h" +#include "py/runtime0.h" +#include "py/nlr.h" +#include "py/objlist.h" +#include "py/objstr.h" +#include "py/runtime.h" +#include "py/mperrno.h" +#include "py/mphal.h" +#include "py/stream.h" +#include "shared/runtime/pyexec.h" +#include "shared/runtime/interrupt_char.h" + + +#if MICROPY_QPY_MODULE_EXAMPLE + +static mp_obj_t example_exec(const mp_obj_t arg0) +{ + int ret = 0; + + mp_buffer_info_t bufinfo; + char fname[128] = {0}; + char path[128] = {0}; + mp_get_buffer_raise(arg0, &bufinfo, MP_BUFFER_READ); + + memcpy(path, bufinfo.buf, bufinfo.len); + + if(bufinfo.buf != NULL) + { + // Pawn 2021-01-18 for JIRA STASR3601-2428 begin + if (path[0] != '/') + { + snprintf(fname, sizeof(fname), "/%s", (char *)bufinfo.buf); + } + else + { + snprintf(fname, sizeof(fname), "%s", (char *)bufinfo.buf); + } + + ret = pyexec_file_if_exists(fname); + } + if ( ret == -1 ) + { + mp_raise_msg_varg(&mp_type_OSError, MP_ERROR_TEXT("File path error or not exist: [%s]"), (char *)bufinfo.buf); + } + #if MICROPY_PY_KBD_EXCEPTION + else if(ret == RET_KBD_INTERRUPT) + { + pyexec_system_exit = PYEXEC_FORCED_EXIT; + MAINPY_INTERRUPT_BY_KBD_FLAG_SET(); + mp_raise_msg_varg(&mp_type_SystemExit, MP_ERROR_TEXT("CTRL_C Interrupt")); + } + #endif + #if MICROPY_PY_SOFT_RESET + else if((ret & PYEXEC_SOFTRESET) == PYEXEC_SOFTRESET) + { + pyexec_system_exit = PYEXEC_FORCED_EXIT; + mp_raise_msg_varg(&mp_type_SystemExit, MP_ERROR_TEXT("SoftReset")); + } + #endif + // Pawn 2021-01-18 for JIRA STASR3601-2428 end + return mp_const_none; +} + + + +static MP_DEFINE_CONST_FUN_OBJ_1(example_exec_obj, example_exec); + + +static mp_obj_t example_initialize() +{ + static int initialized = 0; + if (!initialized) { + initialized = 1; + } + return mp_const_none; +} + +static MP_DEFINE_CONST_FUN_OBJ_0(example_initialize_obj, example_initialize); + +static const mp_rom_map_elem_t mp_module_example_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_example) }, + { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&example_initialize_obj) }, + { MP_ROM_QSTR(MP_QSTR_exec), MP_ROM_PTR(&example_exec_obj) }, + +}; + + +static MP_DEFINE_CONST_DICT(mp_module_example_globals, mp_module_example_globals_table); + + +const mp_obj_module_t example_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&mp_module_example_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_example, example_module); +#endif /* MICROPY_QPY_MODULE_EXAMPLE */ diff --git a/ports/quectel/modflashdev.c b/ports/quectel/modflashdev.c new file mode 100644 index 0000000000000..b2aa939ceb425 --- /dev/null +++ b/ports/quectel/modflashdev.c @@ -0,0 +1,181 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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" + +#if MICROPY_VFS +#include "extmod/vfs.h" +#endif + +#include "helios_flash.h" +#include "helios_debug.h" + +#define MOD_FLASHDEV_LOG(msg, ...) custom_log('flashdev', msg, ##__VA_ARGS__) + +const mp_obj_type_t helios_flash_device_type; + +struct lfs_flash_info +{ + uint32_t FlashType; + uint32_t LfsStartAddress; + uint32_t LfsEndAddress; +}; + +typedef struct _helios_flash_device_obj_t { + mp_obj_base_t base; + int block_size; + int block_count; + struct lfs_flash_info info; + char partition_name[32]; +} helios_flash_device_obj_t; + +static mp_obj_t helios_flash_device_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, 2, false); + helios_flash_device_obj_t *self = mp_obj_malloc(helios_flash_device_obj_t, type); + + mp_buffer_info_t bufinfo; + memset(self->partition_name, 0x0, sizeof(self->partition_name)); + mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ); + if( bufinfo.len >= sizeof(self->partition_name)) { + mp_raise_ValueError(MP_ERROR_TEXT("partition name is invalid")); + } + memcpy(self->partition_name, bufinfo.buf, bufinfo.len); + + self->block_size = mp_obj_get_int(args[1]); + + if (self->block_size <= 0) { + mp_raise_ValueError(MP_ERROR_TEXT("invalid block size")); + } + + HeliosFlashPartiCtx *FlashPartiCtx = Helios_Flash_GetPartiCtx((const char*)self->partition_name); + if(!FlashPartiCtx) mp_raise_OSError(19); + + uint32_t FlashPartiAddr = FlashPartiCtx->addr; + size_t FlashPartiSize = FlashPartiCtx->size; + MOD_FLASHDEV_LOG("flash addr:%x", FlashPartiAddr); + MOD_FLASHDEV_LOG("flash size:%x", FlashPartiSize); + self->info.LfsStartAddress = (FlashPartiAddr) / self->block_size * self->block_size; +#if MICROPY_VFS_LFS2 + self->info.LfsEndAddress = ((FlashPartiAddr + FlashPartiSize) / self->block_size) * self->block_size; +#else + self->info.LfsEndAddress = ((FlashPartiAddr + FlashPartiSize - 1) / self->block_size) * self->block_size; +#endif + + self->block_count = FlashPartiSize / self->block_size; + + return MP_OBJ_FROM_PTR(self); +} + +static mp_obj_t helios_flash_device_readblocks(size_t n_args, const mp_obj_t *args) +{ + helios_flash_device_obj_t *self = MP_OBJ_TO_PTR(args[0]); + uint32_t FlashAddrss = 0; + uint32_t block_num = mp_obj_get_int(args[1]); + uint32_t offset = block_num * self->block_size; + mp_buffer_info_t bufinfo; + int ret; + + if (n_args >= 4) { + offset += mp_obj_get_int(args[3]); + } + + FlashAddrss = self->info.LfsStartAddress + offset; + mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_WRITE); + ret = Helios_Flash_Read((uint32_t)FlashAddrss, bufinfo.buf, bufinfo.len); + return MP_OBJ_NEW_SMALL_INT(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(helios_flash_device_readblocks_obj, 3, 4, helios_flash_device_readblocks); + +static mp_obj_t helios_flash_device_writeblocks(size_t n_args, const mp_obj_t *args) +{ + helios_flash_device_obj_t *self = MP_OBJ_TO_PTR(args[0]); + uint32_t block_num = mp_obj_get_int(args[1]); + uint32_t offset = block_num * self->block_size; + mp_buffer_info_t bufinfo; + int ret; + uint32_t FlashAddrss = self->info.LfsStartAddress + offset; + + if (n_args == 3) { + ret = Helios_Flash_Erase(FlashAddrss, self->block_size); + if (ret) { + return MP_OBJ_NEW_SMALL_INT(ret); + } + } else { + offset += mp_obj_get_int(args[3]); + } + FlashAddrss = self->info.LfsStartAddress + offset; + mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ); + ret = Helios_Flash_Write(FlashAddrss, bufinfo.buf, bufinfo.len); + return MP_OBJ_NEW_SMALL_INT(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(helios_flash_device_writeblocks_obj, 3, 4, helios_flash_device_writeblocks); + +static mp_obj_t helios_flash_device_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t arg_in) +{ + helios_flash_device_obj_t *self = self_in; + mp_int_t cmd = mp_obj_get_int(cmd_in); + mp_int_t block_num = mp_obj_get_int(arg_in); + int ret; + uint32_t FlashAddrss; + + switch (cmd) { + case MP_BLOCKDEV_IOCTL_INIT: + case MP_BLOCKDEV_IOCTL_DEINIT: + case MP_BLOCKDEV_IOCTL_SYNC: + return MP_OBJ_NEW_SMALL_INT(0); + + case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: + return MP_OBJ_NEW_SMALL_INT(self->block_count); + + case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: + return MP_OBJ_NEW_SMALL_INT(self->block_size); + + case MP_BLOCKDEV_IOCTL_BLOCK_ERASE: + FlashAddrss = self->info.LfsStartAddress + (block_num * self->block_size); + ret = Helios_Flash_Erase(FlashAddrss, self->block_size); + return MP_OBJ_NEW_SMALL_INT(ret); + + default: + return MP_OBJ_NEW_SMALL_INT(-1); + } +} +static MP_DEFINE_CONST_FUN_OBJ_3(helios_flash_device_ioctl_obj, helios_flash_device_ioctl); + +static const mp_rom_map_elem_t helios_flash_device_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&helios_flash_device_readblocks_obj) }, + { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&helios_flash_device_writeblocks_obj) }, + { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&helios_flash_device_ioctl_obj) }, +}; +static MP_DEFINE_CONST_DICT(helios_flash_device_locals_dict, helios_flash_device_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + helios_flash_device_type, + MP_QSTR_FlashDevice, + MP_TYPE_FLAG_NONE, + make_new, helios_flash_device_make_new, + locals_dict, &helios_flash_device_locals_dict + ); diff --git a/ports/quectel/modfota.c b/ports/quectel/modfota.c new file mode 100644 index 0000000000000..6a656051a93ac --- /dev/null +++ b/ports/quectel/modfota.c @@ -0,0 +1,446 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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/obj.h" +#include +#include "py/runtime.h" +#include "mphalport.h" +#include "gccollect.h" + + +#if MICROPY_QPY_MODULE_FOTA + +#include "helios_fota.h" +#include "helios_power.h" +#include "helios_debug.h" +#include "callbackdeal.h" +#include "shared/runtime/pyexec.h" + + +#define MOD_FOTA_LOG(msg, ...) custom_log(FOTA, msg, ##__VA_ARGS__) + +typedef struct _fota_obj_t { + mp_obj_base_t base; + int ctx; +}fota_obj_t; + +const mp_obj_type_t mp_fota_type; +static fota_obj_t *fota_self_obj = NULL; + +static char *temp_server_address1 = NULL; + +extern void Helios_Fota_SslConfig(char *rootCA, char *clientCert, char *clientKey); + +#if defined(PLAT_Qualcomm) || defined (PLAT_Unisoc) || defined(PLAT_ASR_1803s) || defined(PLAT_EIGEN) +extern int Helios_Fota_Download_Cancel(void); +extern int Helios_Fota_Reset_Disable(int flag); +extern int Helios_Fota_APN_Set(int ip_type, char *apn, char *user, char *pass); +#endif + +static mp_obj_t fota_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) +{ + if (fota_self_obj == NULL) + { + fota_self_obj = mp_obj_malloc_with_finaliser(fota_obj_t, &mp_fota_type); + } + fota_obj_t *self = fota_self_obj; + + self->base.type = &mp_fota_type; + self->ctx = Helios_Fota_Init(); + +#if defined (PLAT_ASR) || defined (PLAT_Unisoc) || defined(PLAT_Qualcomm) || defined(PLAT_ASR_1803s) || defined(PLAT_EIGEN) + const byte *key = NULL; + const byte *cert = NULL; + const byte *root_cert = NULL; +#if defined(PLAT_Qualcomm) || defined (PLAT_Unisoc) || defined(PLAT_ASR_1803s) || defined(PLAT_EIGEN) + int reset_disable = 0; +#endif + + if (n_args > 0 || n_kw > 0) + { + //ssl args + enum { ARG_key, ARG_cert, ARG_root_cert, ARG_reset_disable}; + + static const mp_arg_t allowed_args[] = { + { MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_root_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_reset_disable, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + }; + + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + // parse args + mp_arg_val_t args_dest[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, args, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args_dest); + + if (args_dest[ARG_key].u_obj != mp_const_none) + { + size_t key_len; + key = (const byte *)mp_obj_str_get_data(args_dest[ARG_key].u_obj, &key_len); + } + + if (args_dest[ARG_cert].u_obj != mp_const_none) + { + size_t cert_len; + cert = (const byte *)mp_obj_str_get_data(args_dest[ARG_cert].u_obj, &cert_len); + } + + if (args_dest[ARG_root_cert].u_obj != mp_const_none) + { + size_t root_cert_len; + root_cert = (const byte *)mp_obj_str_get_data(args_dest[ARG_root_cert].u_obj, &root_cert_len); + } + #if defined(PLAT_Qualcomm) || defined (PLAT_Unisoc) || defined(PLAT_ASR_1803s) || defined(PLAT_EIGEN) + if (args_dest[ARG_reset_disable].u_int != -1) + { + reset_disable = args_dest[ARG_reset_disable].u_int; + } + #endif + } +#if defined(PLAT_Qualcomm) || defined (PLAT_Unisoc) || defined(PLAT_ASR_1803s) || defined(PLAT_EIGEN) + Helios_Fota_Reset_Disable(reset_disable); +#endif + Helios_Fota_SslConfig((char *)(root_cert), (char *)(cert), (char *)(key)); +#endif + return MP_OBJ_FROM_PTR(self); +} + +static mp_obj_t fota_write(size_t n_args, const mp_obj_t *args) +{ + int ret; + int file_size; + + fota_obj_t *self = MP_OBJ_TO_PTR(args[0]); + + if(n_args > 2) + { + file_size = mp_obj_get_int(args[2]); + } + else + { + MOD_FOTA_LOG("*** input param invalid \r\n***"); + return mp_obj_new_int(-1); + } + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); + + MOD_FOTA_LOG(" buff len : %d file_size : %d\r\n", bufinfo.len, file_size); + + MP_THREAD_GIL_EXIT(); + ret = Helios_Fota_PackageWrite(self->ctx, bufinfo.buf, bufinfo.len, (size_t)file_size); + MP_THREAD_GIL_ENTER(); + + if(ret) + { + MOD_FOTA_LOG("*** fota package write fail ***\r\n"); + return mp_obj_new_int(-1); + } + if(ret < 0) + { + MOD_FOTA_LOG("*** fota package file read fail ***\r\n"); + return mp_obj_new_int(-1); + } + + return mp_obj_new_int(0); +} +#if !defined(PLAT_RDA) +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fota_write_obj, 1, 3, fota_write); +#endif + + +static mp_obj_t fota_flush(const mp_obj_t arg0) +{ + int ret = 0; + fota_obj_t *self = MP_OBJ_TO_PTR(arg0); + + ret = Helios_Fota_PackageFlush(self->ctx); + if(ret) + { + MOD_FOTA_LOG("*** fota package flush fail ***\r\n"); + return mp_obj_new_int(-1); + } + MOD_FOTA_LOG("fota package write done, verifing ...\r\n"); + + return mp_obj_new_int(0); +} +#if !defined(PLAT_RDA) +static MP_DEFINE_CONST_FUN_OBJ_1(fota_flush_obj, fota_flush); +#endif +static mp_obj_t fota_verify(const mp_obj_t arg0) +{ + int ret = 0; + fota_obj_t *self = MP_OBJ_TO_PTR(arg0); + MP_THREAD_GIL_EXIT(); + ret = Helios_Fota_PackageVerify(self->ctx); + MP_THREAD_GIL_ENTER(); + + if(ret) + { + MOD_FOTA_LOG("*** fota package verify fail ***\r\n"); + return mp_obj_new_int(-1); + } + MOD_FOTA_LOG("fota package verify done, will restart to update ...\r\n"); + + return mp_obj_new_int(0); +} +#if !defined(PLAT_RDA) +static MP_DEFINE_CONST_FUN_OBJ_1(fota_verify_obj, fota_verify); +#endif +static c_callback_t *fota_callback = NULL; + + +static void mpFotaProgressCB(int sta, int progress) +{ + if(fota_callback != NULL){ + MP_THREAD_GIL_ENTER(); + GC_STACKTOP_SET(); + mp_obj_t fota_list[2] = { + mp_obj_new_int(sta), + mp_obj_new_int(progress), + }; + + mp_sched_schedule_ex(fota_callback, mp_obj_new_list(2, fota_list)); + GC_STACKTOP_CLEAR(); + MP_THREAD_GIL_EXIT(); + } + + if(sta == 1) + { + MOD_FOTA_LOG("fota test downloading (%d)%d ...\r\n", sta, progress); + } + else if(sta == 0) + { + MOD_FOTA_LOG("fota test downloading (%d)%d ...\r\n", sta, progress); + } + else if(sta == 2) + { + MOD_FOTA_LOG("fota test update flag setted, will restart to update ...\r\n"); + #if defined (PLAT_ASR) + Helios_Power_Reset(1); + #endif + } + else if(sta == -1) + { + MOD_FOTA_LOG("fota test download failed (%d)%d\r\n", sta, progress); + MOD_FOTA_LOG("========== fota test end ==========\r\n"); + } +} + +static mp_obj_t fota_get_url() +{ + return mp_obj_new_str(temp_server_address1, strlen(temp_server_address1)); +} +#if defined(PLAT_SONY_ALT1350) +static MP_DEFINE_CONST_FUN_OBJ_0(fota_get_url_obj, fota_get_url); +#endif +static mp_obj_t fota_get_obj() +{ + return MP_OBJ_FROM_PTR(fota_self_obj); +} +#if defined(PLAT_SONY_ALT1350) +static MP_DEFINE_CONST_FUN_OBJ_0(fota_get_obj_obj, fota_get_obj); +#endif + +static mp_obj_t fota_firmware_download(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) +{ + int ret; + char *server_address1 = NULL; + char *server_address2 = NULL; + + enum { + ARG_url1, + ARG_url2, + ARG_callback, + }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_url1, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_url2, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + }; + + mp_arg_val_t args_parse[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args-1, args+1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args_parse); + + if (args_parse[ARG_url1].u_obj != mp_const_none) { + server_address1 = (char *)(mp_obj_str_get_str(args_parse[ARG_url1].u_obj)); + } + + if (args_parse[ARG_url2].u_obj != mp_const_none) { + server_address2 = (char *)(mp_obj_str_get_str(args_parse[ARG_url2].u_obj)); + } + + if (args_parse[ARG_callback].u_obj != mp_const_none) { + static c_callback_t cb = {0}; + memset(&cb, 0, sizeof(c_callback_t)); + fota_callback = &cb; + mp_sched_schedule_callback_register(fota_callback, args_parse[ARG_callback].u_obj); + } + + + MP_THREAD_GIL_EXIT(); + ret = Helios_Fota_firmware_download(server_address1, server_address2, mpFotaProgressCB); + MP_THREAD_GIL_ENTER(); +#if !defined(PLAT_SONY_ALT1350) + if(ret) + { + MOD_FOTA_LOG("*** fota firmware download fail ***\r\n"); + return mp_obj_new_int(-1); + } + return mp_obj_new_int(0); +#else + temp_server_address1 = server_address1; + ret = pyexec_frozen_module("fota_BG950S.py", false); + if(ret == 0) + { + MOD_FOTA_LOG("*** fota execute fail ***\r\n"); + return mp_obj_new_int(-1); + } + return mp_obj_new_int(0); +#endif +} + +static MP_DEFINE_CONST_FUN_OBJ_KW(fota_firmware_download_obj, 1, fota_firmware_download); + +#if defined(PLAT_Qualcomm) +static mp_obj_t fota_download_cancel(const mp_obj_t arg0) +{ + int ret = 0; + + ret = Helios_Fota_Download_Cancel(); + if(ret) + { + MOD_FOTA_LOG("*** fota download cancel fail ***\r\n"); + return mp_obj_new_int(-1); + } + + return mp_obj_new_int(0); +} + +static MP_DEFINE_CONST_FUN_OBJ_1(fota_download_cancel_obj, fota_download_cancel); + +static mp_obj_t fota_apn_set(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) +{ + int ret; + int ip_type = 0; + char *apn = NULL; + char *user = NULL; + char *password = NULL; + + enum { + ARG_ip_type, + ARG_apn, + ARG_user, + ARG_password, + }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_ip_type, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_fota_apn, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_fota_user, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_fota_password, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + }; + + mp_arg_val_t args_parse[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args-1, args+1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args_parse); + + if (args_parse[ARG_ip_type].u_int != -1) + { + ip_type = args_parse[ARG_ip_type].u_int; + } + + if (args_parse[ARG_apn].u_obj != mp_const_none) { + apn = (char *)(mp_obj_str_get_str(args_parse[ARG_apn].u_obj)); + } + + if (args_parse[ARG_user].u_obj != mp_const_none) { + user = (char *)(mp_obj_str_get_str(args_parse[ARG_user].u_obj)); + } + + if (args_parse[ARG_password].u_obj != mp_const_none) { + password = (char *)(mp_obj_str_get_str(args_parse[ARG_password].u_obj)); + } + + ret = Helios_Fota_APN_Set(ip_type, apn, user, password); + + if(ret) + { + return mp_obj_new_int(-1); + } + + return mp_obj_new_int(0); +} + +static MP_DEFINE_CONST_FUN_OBJ_KW(fota_apn_set_obj, 1, fota_apn_set); + +#endif + +static mp_obj_t fota___del__(mp_obj_t self_in) +{ + fota_obj_t *self = MP_OBJ_TO_PTR(self_in); + + Helios_Fota_Deinit(self->ctx); + fota_callback = NULL; + fota_self_obj = NULL; + + return mp_obj_new_int(0); +} +static MP_DEFINE_CONST_FUN_OBJ_1(fota___del___obj, fota___del__); + + +static const mp_rom_map_elem_t fota_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&fota___del___obj) }, + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_fota) }, +#if defined(PLAT_SONY_ALT1350) + { MP_ROM_QSTR(MP_QSTR_fota_get_url), MP_ROM_PTR(&fota_get_url_obj) }, + { MP_ROM_QSTR(MP_QSTR_fota_get_obj), MP_ROM_PTR(&fota_get_obj_obj) }, +#endif +#if !defined(PLAT_RDA) + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&fota_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&fota_flush_obj) }, + { MP_ROM_QSTR(MP_QSTR_verify), MP_ROM_PTR(&fota_verify_obj) }, +#endif + { MP_ROM_QSTR(MP_QSTR_httpDownload), MP_ROM_PTR(&fota_firmware_download_obj) }, +#if defined(PLAT_Qualcomm) + { MP_ROM_QSTR(MP_QSTR_download_cancel), MP_ROM_PTR(&fota_download_cancel_obj) }, + { MP_ROM_QSTR(MP_QSTR_apn_set), MP_ROM_PTR(&fota_apn_set_obj) }, +#endif +}; +static MP_DEFINE_CONST_DICT(fota_locals_dict, fota_locals_dict_table); + + +MP_DEFINE_CONST_OBJ_TYPE( + mp_fota_type, + MP_QSTR_fota, + MP_TYPE_FLAG_NONE, + make_new, fota_make_new, + locals_dict, &fota_locals_dict + ); +MP_REGISTER_MODULE(MP_QSTR_fota, mp_fota_type); + +#endif /* MICROPY_QPY_MODULE_FOTA */ diff --git a/ports/quectel/modhelios.c b/ports/quectel/modhelios.c new file mode 100644 index 0000000000000..47aa360a3a081 --- /dev/null +++ b/ports/quectel/modhelios.c @@ -0,0 +1,57 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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/objstr.h" +#include "py/runtime.h" +#include "py/mperrno.h" +#include "py/mphal.h" + +#include "quectel_version.h" + +static mp_obj_t helios_platform(void) { + char platform[64] = {0}; + snprintf(platform, sizeof(platform), "%s%d.%d.%d", "heliossdk-v", VERSION_MAJOR, VERSION_MINOR, VERSION_MICRO); + return mp_obj_new_str(platform, strlen(platform)); +} +static MP_DEFINE_CONST_FUN_OBJ_0(helios_platform_obj, helios_platform); + +static const mp_rom_map_elem_t helios_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_helios) }, + + { MP_ROM_QSTR(MP_QSTR_platform), MP_ROM_PTR(&helios_platform_obj) }, +}; + +static MP_DEFINE_CONST_DICT(helios_module_globals, helios_module_globals_table); + +const mp_obj_module_t helios_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&helios_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_helios, helios_module); \ No newline at end of file diff --git a/ports/quectel/modmachine.c b/ports/quectel/modmachine.c new file mode 100644 index 0000000000000..2bb59786e980c --- /dev/null +++ b/ports/quectel/modmachine.c @@ -0,0 +1,113 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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 "mpconfigport.h" + +#include "py/compile.h" +#include "py/runtime.h" +#include "py/repl.h" +#include "py/mperrno.h" + +#include "modmachine.h" +#include "shared/runtime/pyexec.h" +#include "mphalport.h" + +#if MICROPY_QPY_MODULE_MACHINE +#if MICROPY_PY_SOFT_RESET +static mp_obj_t machine_soft_reset(void) { + pyexec_system_exit = PYEXEC_FORCED_EXIT; + MP_STATE_VM(mp_softreset_exception).traceback_data = NULL; + MP_STATE_MAIN_THREAD(mp_pending_exception) = MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_softreset_exception)); +#if MICROPY_ENABLE_SCHEDULER + if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) { + MP_STATE_VM(sched_state) = MP_SCHED_PENDING; + } +#endif + + mp_mthread_wakeup(); + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_0(machine_soft_reset_obj, machine_soft_reset); +#endif + + +static const mp_rom_map_elem_t machine_module_globals_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_machine) }, +#if MICROPY_QPY_MACHINE_PIN + { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) }, +#endif +#if MICROPY_QPY_MACHINE_EXTINT + { MP_ROM_QSTR(MP_QSTR_ExtInt), MP_ROM_PTR(&machine_extint_type) }, +#endif +#if MICROPY_QPY_MACHINE_UART + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) }, +#endif +#if MICROPY_QPY_MACHINE_SPI + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_hard_spi_type) }, +#endif +#if MICROPY_QPY_MACHINE_I2C + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_hard_i2c_type) }, +#endif +#if MICROPY_QPY_MACHINE_I2C_SOFT + { MP_ROM_QSTR(MP_QSTR_I2C_simulation), MP_ROM_PTR(&machine_simulation_i2c_type) }, +#endif +#if MICROPY_QPY_MACHINE_TIMER + { MP_OBJ_NEW_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) }, +#endif +#if MICROPY_PY_SOFT_RESET + { MP_ROM_QSTR(MP_QSTR_SoftReset), MP_ROM_PTR(&machine_soft_reset_obj) }, +#endif +#if MICROPY_QPY_MACHINE_RTC + { MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&machine_rtc_type) }, +#endif +#if MICROPY_QPY_MACHINE_LCD + { MP_ROM_QSTR(MP_QSTR_LCD), MP_ROM_PTR(&machine_lcd_type) }, +#endif +#if MICROPY_QPY_MACHINE_WDT + { MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&machine_wdt_type) }, +#endif +#if MICROPY_QPY_MACHINE_KEYPAD + { MP_ROM_QSTR(MP_QSTR_KeyPad), MP_ROM_PTR(&machine_keypad_type) }, +#endif +#if MICROPY_QPY_MACHINE_NANDFLASH + { MP_ROM_QSTR(MP_QSTR_NANDFLASH), MP_ROM_PTR(&machine_nandflash_type) }, +#endif +}; + +static MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table); + +const mp_obj_module_t mp_module_machine = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&machine_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_machine, mp_module_machine); + +#endif /* MICROPY_QPY_MODULE_MACHINE */ + diff --git a/ports/quectel/modmachine.h b/ports/quectel/modmachine.h new file mode 100644 index 0000000000000..31bf023fcbd39 --- /dev/null +++ b/ports/quectel/modmachine.h @@ -0,0 +1,53 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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 __MOD_MACHINE_H_ +#define __MOD_MACHINE_H_ + +#include "py/obj.h" + +extern const mp_obj_type_t machine_lcd_type; +extern const mp_obj_type_t machine_pin_type; +extern const mp_obj_type_t machine_uart_type; +extern const mp_obj_type_t machine_extint_type; +extern const mp_obj_type_t machine_rtc_type; +extern const mp_obj_type_t machine_timer_type; +extern const mp_obj_type_t machine_hard_i2c_type; +extern const mp_obj_type_t machine_simulation_i2c_type; +extern const mp_obj_type_t machine_hard_spi_type; +extern const mp_obj_type_t machine_wdt_type; +extern const mp_obj_type_t machine_nandflash_type; +#if defined(PLAT_ASR) || defined(PLAT_Unisoc) ||defined(PLAT_ASR_1606) +extern const mp_obj_type_t machine_keypad_type; +#endif + + + +// void machine_timer_deinit_all(void); + +#endif /* __MOD_MACHINE_H_ */ + + diff --git a/ports/quectel/modmisc.c b/ports/quectel/modmisc.c new file mode 100644 index 0000000000000..62f88e2bec98d --- /dev/null +++ b/ports/quectel/modmisc.c @@ -0,0 +1,253 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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 "mpconfigport.h" + +#include "py/compile.h" +#include "py/runtime.h" +#include "py/repl.h" +#include "py/mperrno.h" +#include "py/obj.h" // Pawn 2020-12-19 Add replEnable + +#if MICROPY_QPY_MODULE_MISC + +#include "helios_dev.h" +#include "modmisc.h" + +#if MICROPY_QPY_MISC_PWM +#include "helios_gpio.h" +#endif + +int repl_protect_enable=0; +#if MICROPY_PY_REPL_PASSWORD_PROTECT +extern int repl_protect_password_enable; +extern char g_repl_protect_pswd[64+1]; +#endif + +static mp_obj_t qpy_misc_set_replEnable(size_t n_args, const mp_obj_t *args) +{ + int flag; + + flag = mp_obj_get_int(args[0]); +#if !MICROPY_PY_REPL_PASSWORD_PROTECT + if (flag != 0 && flag != 1) + { + return mp_obj_new_int(-1); + } +#else + if (flag != 0 && flag != 1 && flag != 2) + { + return mp_obj_new_int(-1); + } + + if (flag == 2) { + if (n_args > 1) { + return mp_obj_new_int(-1); + } else { + if ((strlen(g_repl_protect_pswd) > 0) && (repl_protect_enable == 1)) { + return mp_obj_new_int(4); //repl-protection by password + } else if ((strlen(g_repl_protect_pswd) <= 0) && (repl_protect_enable == 1)) { + return mp_obj_new_int(3); //repl refuse + } else if ((strlen(g_repl_protect_pswd) > 0) && (repl_protect_enable == 0)) { + return mp_obj_new_int(2); //repl enable but The password has already been set + } else { + return mp_obj_new_int(1); //repl enable + } + } + } + + mp_buffer_info_t bufinfo = {0}; + if (strlen(g_repl_protect_pswd) > 0) + { + if (n_args > 1) + { + mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); + if ((bufinfo.len > 0) && (strcmp(g_repl_protect_pswd, bufinfo.buf) == 0)) + { + repl_protect_enable = flag; + } + else + { + return mp_obj_new_int(-1); + } + } + else + { + return mp_obj_new_int(-1); + } + } + else +#endif + { + repl_protect_enable = flag; + } + + return mp_obj_new_int(0); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_misc_set_replEnable_obj, 1, 2, qpy_misc_set_replEnable); + +static mp_obj_t qpy_misc_set_repl_password(size_t n_args, const mp_obj_t *args) +{ +#if MICROPY_PY_REPL_PASSWORD_PROTECT + mp_buffer_info_t bufinfo[2] = {0}; + mp_get_buffer_raise(args[0], &bufinfo[0], MP_BUFFER_READ); + + if (strlen(g_repl_protect_pswd) > 0) /*repl-protection by password*/ + { + if (n_args < 2) + return mp_obj_new_int(-1); + + mp_get_buffer_raise(args[1], &bufinfo[1], MP_BUFFER_READ); + if (bufinfo[1].len > 0) + { + if (strcmp(g_repl_protect_pswd, bufinfo[1].buf) == 0) + { + memset(g_repl_protect_pswd, 0, sizeof(g_repl_protect_pswd)); + if (bufinfo[0].len > 0) + { + repl_protect_password_enable = 1; + strncpy(g_repl_protect_pswd, bufinfo[0].buf, bufinfo[0].len); + } + else + { + repl_protect_password_enable = 0; + } + } + else + { + return mp_obj_new_int(-1); + } + } + else + { + return mp_obj_new_int(-1); + } + } + else + { + memset(g_repl_protect_pswd, 0, sizeof(g_repl_protect_pswd)); + if (bufinfo[0].len > 0) + { + repl_protect_password_enable = 1; + strncpy(g_repl_protect_pswd, bufinfo[0].buf, bufinfo[0].len); + } + else + { + repl_protect_password_enable = 0; + } + } + +#endif + return mp_obj_new_int(0); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_misc_set_repl_password_obj, 1, 2, qpy_misc_set_repl_password); + +#if !defined(PLAT_ASR_1803s) +#if defined(PLAT_ASR) +static mp_obj_t qpy_misc_IncCoreVoltage(void) +{ + if(0 != Helios_Dev_IncreaseCoreVoltage()) { + mp_obj_new_int(-1); + } + return mp_obj_new_int(0); +} +static MP_DEFINE_CONST_FUN_OBJ_0(qpy_misc_IncCoreVoltage_obj, qpy_misc_IncCoreVoltage); +#endif + +#endif + +#if MICROPY_QPY_MISC_CFG_NETLIGHT //20220620 add net light nv @jimmy +static mp_obj_t net_light_enable(size_t n_args,const mp_obj_t *args) +{ + int ret = 0; + if(n_args == 1) + { + int value = mp_obj_get_int(args[0]); + if((value == 0) || (value == 1)) + { + ret = Helios_netlight_enable(value); + } + else + { + ret = -1; + } + } + else + { + ret = Helios_netlight_state_get(); + } + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(net_light_enable_obj, 0, 1, net_light_enable); +#endif + +static const mp_rom_map_elem_t misc_module_globals_table[] = { + + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_misc) }, +#if MICROPY_QPY_MISC_POWER + { MP_ROM_QSTR(MP_QSTR_Power), MP_ROM_PTR(&misc_power_type) }, +#endif +#if MICROPY_QPY_MISC_ADC + { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&misc_adc_type) }, +#endif +#if MICROPY_QPY_MISC_POWERKEY + { MP_ROM_QSTR(MP_QSTR_PowerKey), MP_ROM_PTR(&misc_powerkey_type) }, +#endif +#if MICROPY_QPY_MISC_TEMPERATURE + { MP_ROM_QSTR(MP_QSTR_Temperature), MP_ROM_PTR(&machine_temperature_type) }, +#endif +#if MICROPY_QPY_MISC_PWM + { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&misc_pwm_type) }, + { MP_ROM_QSTR(MP_QSTR_PWM_V2), MP_ROM_PTR(&misc_pwm_v2_type) }, +#endif +#if MICROPY_QPY_MISC_USB + { MP_ROM_QSTR(MP_QSTR_USB), MP_ROM_PTR(&misc_usb_type) }, +#endif +#if MICROPY_QPY_MISC_USBNET + { MP_ROM_QSTR(MP_QSTR_USBNET), MP_ROM_PTR(&misc_usbnet_module) }, +#endif + { MP_ROM_QSTR(MP_QSTR_replEnable), MP_ROM_PTR(&qpy_misc_set_replEnable_obj) }, + { MP_ROM_QSTR(MP_QSTR_replUpdatePassswd), MP_ROM_PTR(&qpy_misc_set_repl_password_obj) }, +#if defined(PLAT_ASR) + { MP_ROM_QSTR(MP_QSTR_IncCoreVoltage), MP_ROM_PTR(&qpy_misc_IncCoreVoltage_obj)}, +#endif +#if MICROPY_QPY_MISC_CFG_NETLIGHT + { MP_ROM_QSTR(MP_QSTR_net_light), MP_ROM_PTR(&net_light_enable_obj) }, +#endif +}; +static MP_DEFINE_CONST_DICT(misc_module_globals, misc_module_globals_table); + +const mp_obj_module_t mp_module_misc = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&misc_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_misc, mp_module_misc); +#endif /* MICROPY_QPY_MODULE_MISC */ + diff --git a/ports/quectel/modmisc.h b/ports/quectel/modmisc.h new file mode 100644 index 0000000000000..5c71ad5c217e8 --- /dev/null +++ b/ports/quectel/modmisc.h @@ -0,0 +1,48 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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 __MOD_MISC_H_ +#define __MOD_MISC_H_ + +#include "py/obj.h" + + +extern const mp_obj_type_t misc_power_type; +extern const mp_obj_type_t misc_pwm_type; +extern const mp_obj_type_t misc_pwm_v2_type; +extern const mp_obj_type_t misc_adc_type; +extern const mp_obj_type_t misc_usb_type; +#if MICROPY_QPY_MISC_USBNET +extern const mp_obj_module_t misc_usbnet_module; +#endif +extern const mp_obj_type_t misc_powerkey_type; + +#if defined(PLAT_RDA) +extern const mp_obj_module_t machine_temperature_type; +#endif + +#endif /* __MOD_MISC_H_ */ + diff --git a/ports/quectel/modnet.c b/ports/quectel/modnet.c new file mode 100644 index 0000000000000..167e360f766ef --- /dev/null +++ b/ports/quectel/modnet.c @@ -0,0 +1,2423 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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 "obj.h" +#include "runtime.h" +#include "mphalport.h" +#include "callbackdeal.h" +#include "gccollect.h" + +#if MICROPY_QPY_MODULE_NET + +#include "helios_debug.h" +#include "helios_nw.h" +#include "helios_dev.h" +#include "helios_sim.h" +#include "helios_datacall.h" +#include "helios_atcmd.h" + +#define QPY_NET_LOG(msg, ...) custom_log(modnet, msg, ##__VA_ARGS__) + +extern int _get_current_simid(void); +/*=============================================================================*/ +/* FUNCTION: qpy_net_set_mode */ +/*=============================================================================*/ +/*!@brief: set network mode + * + * @mode [in] network mode + * @roaming [in] enable or disable roaming + * + * @return: + * 0 - success + * -1 - error + */ +/*=============================================================================*/ +static mp_obj_t qpy_net_set_configuration(size_t n_args, const mp_obj_t *args) +{ + int mode; + int roaming; + int ret = 0; + Helios_NwConfigInfoStruct config_info; + memset(&config_info, 0, sizeof(Helios_NwConfigInfoStruct)); + + mode = mp_obj_get_int(args[0]); + QPY_NET_LOG("[network] set config, mode=%d\r\n", mode); + + int cur_simid = _get_current_simid(); + + if (n_args == 2) + { + roaming = mp_obj_get_int(args[1]); + if((roaming != 0) && (roaming != 1)) + { + QPY_NET_LOG("[network] invalid roaming value, roaming=%d\r\n", roaming); + return mp_obj_new_int(-1); + } + config_info.roaming_switch = roaming; + QPY_NET_LOG("[network] set config, roaming=%d\r\n", roaming); + } + if (n_args ==3) + { + cur_simid = mp_obj_get_int(args[2]); + } + if ((cur_simid != 0) && (cur_simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); + } + config_info.net_mode = mode; + + MP_THREAD_GIL_EXIT(); + ret = Helios_Nw_SetConfiguration(cur_simid, &config_info); + MP_THREAD_GIL_ENTER(); + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_net_set_configuration_obj, 1, 3, qpy_net_set_configuration); + + +/*=============================================================================*/ +/* FUNCTION: qpy_net_get_mode */ +/*=============================================================================*/ +/*!@brief: get network mode + * + * @return: + * returns net mode on success. + * -1 - error + */ +/*=============================================================================*/ +static mp_obj_t qpy_net_get_configuration(size_t n_args, const mp_obj_t *args) +{ + int ret = 0; + Helios_NwConfigInfoStruct config_info; + memset(&config_info, 0, sizeof(Helios_NwConfigInfoStruct)); + + int cur_simid = _get_current_simid(); + if (n_args ==1) + { + cur_simid = mp_obj_get_int(args[0]); + } + if ((cur_simid != 0) && (cur_simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); + } + MP_THREAD_GIL_EXIT(); + ret = Helios_Nw_GetConfiguration(cur_simid, &config_info); + MP_THREAD_GIL_ENTER(); + if(ret == 0) + { + mp_obj_t tuple[2] = {mp_obj_new_int(config_info.net_mode), mp_obj_new_bool(config_info.roaming_switch)}; + return mp_obj_new_tuple(2, tuple); + } + return mp_obj_new_int(-1); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_net_get_configuration_obj, 0, 1, qpy_net_get_configuration); + + +/*=============================================================================*/ +/* FUNCTION: qpy_net_get_csq */ +/*=============================================================================*/ +/*!@brief: get CSQ signal strength + * + * @return: + * returns CSQ on success + * -1 - error + */ +/*=============================================================================*/ +static mp_obj_t qpy_net_get_csq(size_t n_args, const mp_obj_t *args) +{ + int ret = 0; + int csq = -1; + uint8_t status = 0; + int cur_simid = _get_current_simid(); + if (n_args ==1) + { + cur_simid = mp_obj_get_int(args[0]); + } + if ((cur_simid != 0) && (cur_simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); + } + MP_THREAD_GIL_EXIT(); + ret = Helios_SIM_GetCardStatus(cur_simid, (Helios_SIM_Status_e *)&status); + MP_THREAD_GIL_ENTER(); + if (ret == 0) + { + if (status != 1) + { + return mp_obj_new_int(99); + } + } + else + { + return mp_obj_new_int(-1); + } + MP_THREAD_GIL_EXIT(); + csq = Helios_Nw_GetCSQ(cur_simid); + MP_THREAD_GIL_ENTER(); + if(csq != -1) + { + return mp_obj_new_int(csq); + } + + return mp_obj_new_int(-1); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_net_get_csq_obj, 0, 1, qpy_net_get_csq); + +/*=============================================================================*/ +/* FUNCTION: qpy_net_get_nitz_time */ +/*=============================================================================*/ +/*!@brief: get nitz time + * + * @return: + * returns nitz time on success + * -1 - error + */ +/*=============================================================================*/ +static mp_obj_t qpy_net_get_nitz_time(void) +{ + int ret = 0; + Helios_NwNITZTimeInfoStruct info; + memset(&info, 0, sizeof(Helios_NwNITZTimeInfoStruct)); + MP_THREAD_GIL_EXIT(); + ret = Helios_Nw_GetNITZTime(&info); + MP_THREAD_GIL_ENTER(); + if (ret == 0) + { + QPY_NET_LOG("nitz_time:%s\r\n",info.nitz_time); + mp_obj_t tuple[3] = { + mp_obj_new_str(info.nitz_time, strlen(info.nitz_time)), + mp_obj_new_int_from_ull(info.abs_time), + mp_obj_new_int(info.leap_sec)}; + + return mp_obj_new_tuple(3, tuple); + } + + return mp_obj_new_int(-1); +} +static MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_nitz_time_obj, qpy_net_get_nitz_time); + + +/*=============================================================================*/ +/* FUNCTION: qpy_net_get_operator_name */ +/*=============================================================================*/ +/*!@brief: get operator name + * + * @return: + * returns operator name on success + * -1 - error + */ +/*=============================================================================*/ +static mp_obj_t qpy_net_get_operator_name(size_t n_args, const mp_obj_t *args) +{ + int ret = 0; + Helios_NwOperatorInfoStruct info; + Helios_NwRegisterStatusInfoStruct reg_info; + memset(&info, 0, sizeof(Helios_NwOperatorInfoStruct)); + memset(®_info, 0, sizeof(Helios_NwRegisterStatusInfoStruct)); + + int cur_simid = _get_current_simid(); + if (n_args ==1) + { + cur_simid = mp_obj_get_int(args[0]); + } + if ((cur_simid != 0) && (cur_simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); + } + MP_THREAD_GIL_EXIT(); + ret = Helios_Nw_GetRegisterStatus(cur_simid, ®_info); + MP_THREAD_GIL_ENTER(); + + if (ret == 0) + { + if ((reg_info.data_reg.status != 1) && (reg_info.data_reg.status != 5)) + { + QPY_NET_LOG("nw is not registered\r\n"); + return mp_obj_new_int(-1); + } + } + else + { + QPY_NET_LOG("get nw register status failed.\r\n"); + return mp_obj_new_int(-1); + } + + MP_THREAD_GIL_EXIT(); + ret = Helios_Nw_GetOperatorName(cur_simid, &info); + MP_THREAD_GIL_ENTER(); + + if (ret == 0) + { + mp_obj_t tuple[4] = { + mp_obj_new_str(info.long_name, strlen(info.long_name)), + mp_obj_new_str(info.short_name, strlen(info.short_name)), + mp_obj_new_str(info.mcc, strlen(info.mcc)), + mp_obj_new_str(info.mnc, strlen(info.mnc))}; + + return mp_obj_new_tuple(4, tuple); + } + + return mp_obj_new_int(-1); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_net_get_operator_name_obj, 0, 1, qpy_net_get_operator_name); + + +/*=============================================================================*/ +/* FUNCTION: qpy_net_get_selection */ +/*=============================================================================*/ +/*!@brief: get network selection + * + * @return: + * returns (nw_selection,mcc, mnc, act) on success + * -1 - error + */ +/*=============================================================================*/ +static mp_obj_t qpy_net_get_selection(size_t n_args, const mp_obj_t *args) +{ + int ret = 0; + Helios_NwSelectionInfoStruct info; + memset(&info, 0, sizeof(Helios_NwSelectionInfoStruct)); + + int cur_simid = _get_current_simid(); + if (n_args ==1) + { + cur_simid = mp_obj_get_int(args[0]); + } + if ((cur_simid != 0) && (cur_simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); + } + MP_THREAD_GIL_EXIT(); + ret = Helios_Nw_GetSelection(cur_simid, &info); + MP_THREAD_GIL_ENTER(); + if (ret == 0) + { + mp_obj_t tuple[4] = { + mp_obj_new_int(info.nw_selection_mode), + mp_obj_new_str(info.mcc, strlen(info.mcc)), + mp_obj_new_str(info.mnc, strlen(info.mnc)), + mp_obj_new_int(info.act)}; + + return mp_obj_new_tuple(4, tuple); + } + return mp_obj_new_int(-1); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_net_get_selection_obj, 0, 1, qpy_net_get_selection); + + +/*=============================================================================*/ +/* FUNCTION: qpy_net_get_reg_status */ +/*=============================================================================*/ +/*!@brief: get information about network registration + * + * @return: + * returns information about network registration on success + * -1 - error + */ +/*=============================================================================*/ +static mp_obj_t qpy_net_get_reg_status(size_t n_args, const mp_obj_t *args) +{ + int ret = 0; + Helios_NwRegisterStatusInfoStruct info; + memset(&info, 0, sizeof(Helios_NwRegisterStatusInfoStruct)); + + int cur_simid = _get_current_simid(); + if (n_args ==1) + { + cur_simid = mp_obj_get_int(args[0]); + } + if ((cur_simid != 0) && (cur_simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); + } + MP_THREAD_GIL_EXIT(); + ret = Helios_Nw_GetRegisterStatus(cur_simid, &info); + MP_THREAD_GIL_ENTER(); + if (ret == 0) + { + mp_obj_t voice_list[6] = { + mp_obj_new_int(info.voice_reg.status), + mp_obj_new_int(info.voice_reg.lac), + mp_obj_new_int(info.voice_reg.cid), + mp_obj_new_int(info.voice_reg.act), + mp_obj_new_int(info.voice_reg.reject_cause), + mp_obj_new_int(info.voice_reg.psc) + }; + + mp_obj_t data_list[6] = { + mp_obj_new_int(info.data_reg.status), + mp_obj_new_int(info.data_reg.lac), + mp_obj_new_int(info.data_reg.cid), + mp_obj_new_int(info.data_reg.act), + mp_obj_new_int(info.data_reg.reject_cause), + mp_obj_new_int(info.data_reg.psc) + }; + + mp_obj_t tuple[2] = { + mp_obj_new_list(6,voice_list), + mp_obj_new_list(6,data_list)}; + return mp_obj_new_tuple(2, tuple); + } + return mp_obj_new_int(-1); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_net_get_reg_status_obj, 0, 1, qpy_net_get_reg_status); + + +/*=============================================================================*/ +/* FUNCTION: qpy_net_get_signal_strength */ +/*=============================================================================*/ +/*!@brief: get signal strength + * + * @return: + * returns information about signal strength on success + * -1 - error + */ +/*=============================================================================*/ +static mp_obj_t qpy_net_get_signal_strength(size_t n_args, const mp_obj_t *args) +{ + int ret = 0; + Helios_NwSignalStrengthInfoStruct info; + memset(&info, 0, sizeof(Helios_NwSignalStrengthInfoStruct)); + int cur_simid = _get_current_simid(); + if (n_args ==2) + { + cur_simid = mp_obj_get_int(args[1]); + } + if ((cur_simid != 0) && (cur_simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); + } + MP_THREAD_GIL_EXIT(); + ret = Helios_Nw_GetSignalStrength(cur_simid, &info); + MP_THREAD_GIL_ENTER(); + + if (ret == 0) + { + mp_obj_t gw_list[4] = { + mp_obj_new_int(info.gw_signal_strength.rssi), + mp_obj_new_int(info.gw_signal_strength.bit_error_rate), + mp_obj_new_int(info.gw_signal_strength.rscp), + mp_obj_new_int(info.gw_signal_strength.ecno)}; + + #if !defined (PLAT_RDA) //defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_Qualcomm) || defined(PLAT_Unisoc) || defined(PLAT_ASR) + if (n_args > 0) + { + int flag = mp_obj_get_int(args[0]); + if (flag == 1) + { + mp_obj_t lte_list[5] = { + mp_obj_new_int(info.lte_signal_strength.rssi), + mp_obj_new_int(info.lte_signal_strength.rsrp), + mp_obj_new_int(info.lte_signal_strength.rsrq), + mp_obj_new_int(info.lte_signal_strength.cqi), + mp_obj_new_int(info.lte_signal_strength.sinr)}; + + mp_obj_t tuple[2] = { + mp_obj_new_list(4,gw_list), + mp_obj_new_list(5,lte_list)}; + + return mp_obj_new_tuple(2, tuple); + } + } + #endif + mp_obj_t lte_list[4] = { + mp_obj_new_int(info.lte_signal_strength.rssi), + mp_obj_new_int(info.lte_signal_strength.rsrp), + mp_obj_new_int(info.lte_signal_strength.rsrq), + mp_obj_new_int(info.lte_signal_strength.cqi)}; + + mp_obj_t tuple[2] = { + mp_obj_new_list(4,gw_list), + mp_obj_new_list(4,lte_list)}; + + return mp_obj_new_tuple(2, tuple); + } + return mp_obj_new_int(-1); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_net_get_signal_strength_obj, 0, 2, qpy_net_get_signal_strength); + + +/*=============================================================================*/ +/* FUNCTION: qpy_net_get_mnc */ +/*=============================================================================*/ +/*!@brief: get mnc + * + * @return: + * returns mnc on success + * -1 - error + */ +/*=============================================================================*/ +static mp_obj_t qpy_net_get_mnc(size_t n_args, const mp_obj_t *args) +{ + int ret = 0; + int i = 0; + mp_obj_t mnc_list = mp_obj_new_list(0, NULL); + Helios_NwCellInfoStruct info; + memset(&info, 0, sizeof(Helios_NwCellInfoStruct)); + int cur_simid = _get_current_simid(); + if (n_args ==1) + { + cur_simid = mp_obj_get_int(args[0]); + } + if ((cur_simid != 0) && (cur_simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); + } + MP_THREAD_GIL_EXIT(); + ret = Helios_Nw_GetCellInfo(cur_simid, &info); + MP_THREAD_GIL_ENTER(); + + if (ret == 0) + { + if (info.gsm_info_num > 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 3)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, net_type should be in [0,%d]."), HELIOS_BAND_TYPE_MAX_NUM); + } + if ((gsm_band < 0) || (gsm_band > 0x0f)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, gsm_band should be in [0,%x]."), HELIOS_BAND_GSM_MAXVALUE); + } + + size_t len = 0; + mp_obj_t *elem = NULL; + mp_obj_get_array(args[2], &len, &elem); + QPY_NET_LOG("[helios_nw_band]elem num : %d\r\n", len); + if (len != 4) + { + mp_raise_ValueError("invalid value, band tuple should be 4 uint32 elements."); + } + + uint32_t band_hh = mp_obj_get_int_truncated(elem[0]); + uint32_t band_hl = mp_obj_get_int_truncated(elem[1]); + uint32_t band_lh = mp_obj_get_int_truncated(elem[2]); + uint32_t band_ll = mp_obj_get_int_truncated(elem[3]); + QPY_NET_LOG("[helios_nw_band]band_hh=%x, band_hl=%x, band_lh=%x, band_ll=%x\r\n", band_hh, band_hl, band_lh, band_ll); + + Helios_NwBandStruct band_info; + memset(&band_info, 0, sizeof(Helios_NwBandStruct)); + band_info.band_type = net_type; + band_info.band_gsm = gsm_band; + band_info.band_low = (((uint64_t)band_lh) << 32) | band_ll; + band_info.band_hign = (((uint64_t)band_hh) << 32) | band_hl; + QPY_NET_LOG("[helios_nw_band]bandh=%llx, bandl=%llx\r\n", band_info.band_hign, band_info.band_low); + + int cur_simid = _get_current_simid(); + MP_THREAD_GIL_EXIT(); + ret = Helios_Nw_SetBand(cur_simid, &band_info); + MP_THREAD_GIL_ENTER(); + return ((ret == 0) ? mp_obj_new_int(0) : mp_obj_new_int(ret)); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_net_set_band_obj, 3, 3, qpy_net_set_band); + +static mp_obj_t qpy_net_get_band(mp_obj_t net_type) +{ + int band_type = mp_obj_get_int(net_type); + if ((band_type < 0) || (band_type > 3)) + { + mp_raise_ValueError(MP_ERROR_TEXT("invalid value, net_type should be in [0,3].")); + } + + int ret = 0; + Helios_NwBandStruct band_info; + memset(&band_info, 0, sizeof(Helios_NwBandStruct)); + band_info.band_type = band_type; + int cur_simid = _get_current_simid(); + MP_THREAD_GIL_EXIT(); + ret = Helios_Nw_GetBand(cur_simid, &band_info); + MP_THREAD_GIL_ENTER(); + if (ret == 0) + { + char str[64] = {0}; + if (band_type == HELIOS_GSM_BAND) + { + snprintf(str, 64, "0x%x", band_info.band_gsm); + } + else + { + if (band_info.band_hign == 0) + { +#if MICROPY_QPY_MODULE_NET_BAND + uint32_t band_lh = band_info.band_low >> 32; + uint32_t band_ll = band_info.band_low & 0xFFFFFFFF; + QPY_NET_LOG("[helios_nw_band]band_hign=%lx, band_low=%lx\r\n", band_lh, band_ll); + if (band_lh ==0) { + snprintf(str, 64, "0x%lx", band_ll); + } else { + snprintf(str, 64, "0x%lx%08lx", band_lh, band_ll); + } +#else + snprintf(str, 64, "0x%llx", band_info.band_low); +#endif + } + else + { + snprintf(str, 64, "0x%llx%016llx", band_info.band_hign, band_info.band_low); + } + } + return mp_obj_new_str(str, strlen(str)); + } + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_1(qpy_net_get_band_obj, qpy_net_get_band); +#endif + +#if defined(PLAT_ASR) || MICROPY_QPY_MODULE_NET_BAND +static mp_obj_t qpy_net_band_restore(void) +{ + int ret = 0; + int cur_simid = _get_current_simid(); + MP_THREAD_GIL_EXIT(); + ret = Helios_Nw_Band_Restore(cur_simid); + MP_THREAD_GIL_ENTER(); + + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_band_restore_obj, qpy_net_band_restore); +#endif +/*=============================================================================*/ +/* FUNCTION: qpy_net_get_cell_info */ +/*=============================================================================*/ +/*!@brief: get cell informations + * + * @return: + * returns cell informations on success + * -1 - error + */ +/*=============================================================================*/ +static mp_obj_t qpy_net_get_cell_info(size_t n_args, const mp_obj_t *args) +{ + int i = 0; + int ret = 0; + + mp_obj_t list_gsm = mp_obj_new_list(0, NULL); + mp_obj_t list_umts = mp_obj_new_list(0, NULL); + mp_obj_t list_lte = mp_obj_new_list(0, NULL); + Helios_NwCellInfoStruct info; + memset(&info, 0, sizeof(Helios_NwCellInfoStruct)); + + int cur_simid = _get_current_simid(); +#if defined(PLAT_RDA) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) || defined(PLAT_SONY_ALT1350) + int flag_args = -1; +#else + if (n_args ==1) + { + cur_simid = mp_obj_get_int(args[0]); + } + if ((cur_simid != 0) && (cur_simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); + } +#endif + MP_THREAD_GIL_EXIT(); + ret = Helios_Nw_GetCellInfo(cur_simid, &info); + MP_THREAD_GIL_ENTER(); + + if (ret == 0) + { + if (info.gsm_info_num > 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + #if defined(PLAT_RDA) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) || defined(PLAT_SONY_ALT1350) + if (n_args > 0) + { + flag_args = mp_obj_get_int(args[0]); + + if (flag_args == 1) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 1 ) + { + rst = mp_obj_get_int(args[1]); + } + + modem_fun = (uint8_t)mp_obj_get_int(args[0]); + + #if MICROPY_QPY_MODULE_DSDS + int cur_simid = _get_current_simid(); + if (n_args ==3) + { + cur_simid = mp_obj_get_int(args[2]); + } + if ((cur_simid != 0) && (cur_simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); + } + MP_THREAD_GIL_EXIT(); + ret = Helios_Dev_SetModemFunction(modem_fun, rst, cur_simid); + MP_THREAD_GIL_ENTER(); + #else + MP_THREAD_GIL_EXIT(); + ret = Helios_Dev_SetModemFunction(modem_fun, rst,0); + MP_THREAD_GIL_ENTER(); + #endif + if (ret == 0) + { + return mp_obj_new_int(0); + } + + return mp_obj_new_int(-1); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_net_set_modem_fun_obj, 1, 3, qpy_net_set_modem_fun); + +static mp_obj_t qpy_net_set_apn(size_t n_args, const mp_obj_t *args) +{ +#if defined(PLAT_Qualcomm) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || (defined(PLAT_Unisoc) && !defined(BOARD_EG915UEU_AB)) \ + || defined(PLAT_ASR) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_ASR_1602) || defined(PLAT_Unisoc_8910_R06) + if (n_args == 2) + { + mp_buffer_info_t apninfo = {0}; + mp_get_buffer_raise(args[0], &apninfo, MP_BUFFER_READ); + uint8_t net_simid = mp_obj_get_int(args[1]); + int ret = 0; + if (net_simid != 0) + { + mp_raise_ValueError(MP_ERROR_TEXT("invalid simid.")); + } + if (apninfo.len > HELIOS_APN_LEN_MAX) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, the length of apn should be no more than [%d] bytes."), HELIOS_APN_LEN_MAX); + } + MP_THREAD_GIL_EXIT(); + ret = Helios_Nw_SetApn((char *)apninfo.buf, net_simid); + MP_THREAD_GIL_ENTER(); + if (ret == 0) + { + return mp_obj_new_int(0); + } + return mp_obj_new_int(-1); + } + else +#endif + { + if (n_args == 7)//pid/iptype/apn/usrname/pwd/authtype/simid + { + int8_t ret = 0; + uint8_t net_simid = mp_obj_get_int(args[6]); + uint8_t profile_id = mp_obj_get_int(args[0]); + int ip_type = mp_obj_get_int(args[1]); + int auth_type = mp_obj_get_int(args[5]); + + mp_buffer_info_t apninfo = {0}; + mp_buffer_info_t usrinfo = {0}; + mp_buffer_info_t pwdinfo = {0}; + mp_get_buffer_raise(args[2], &apninfo, MP_BUFFER_READ); + mp_get_buffer_raise(args[3], &usrinfo, MP_BUFFER_READ); + mp_get_buffer_raise(args[4], &pwdinfo, MP_BUFFER_READ); + + int min_profile_id = (int)HELIOS_PROFILE_IDX_MIN; + int max_profile_id = (int)HELIOS_PROFILE_IDX_MAX; + + #if MICROPY_QPY_MODULE_DSDS + if ((net_simid != 0) && (net_simid != 1)) + #else + if (net_simid != 0) + #endif + { + mp_raise_ValueError(MP_ERROR_TEXT("invalid simid.")); + } + if ((profile_id < min_profile_id) || (profile_id > max_profile_id)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, profileIdx should be in [%d,%d]."), min_profile_id, max_profile_id); + } + if ((ip_type < 0) || (ip_type > HELIOS_PDP_TYPE_NUM - 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, ipType should be in [0~%d]."), HELIOS_PDP_TYPE_NUM-1); + } + if ((auth_type < 0) || (auth_type > HELIOS_AUTH_TYPE_NUM - 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, authType should be in [0~%d]."), HELIOS_AUTH_TYPE_NUM-1); + } + if (apninfo.len > HELIOS_APN_LEN_MAX) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, the length of apn should be no more than [%d] bytes."), HELIOS_APN_LEN_MAX); + } + if (usrinfo.len > HELIOS_USR_LEN_MAX) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, the length of username should be no more than [%d] bytes."), HELIOS_USR_LEN_MAX); + } + if (pwdinfo.len > HELIOS_PWD_LEN_MAX) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, the length of password should be no more than [%d] bytes."), HELIOS_PWD_LEN_MAX); + } + + QPY_NET_LOG("[NW-PDNINFO] profile_idx=%d, ip_version=%d, auth_type=%d\r\n", profile_id, ip_type, auth_type); + QPY_NET_LOG("[NW-PDNINFO] anp_name=%s, usr_name=%s, password=%s\r\n", apninfo.buf, usrinfo.buf, pwdinfo.buf); + + Helios_DataCallStartStruct pdpinfo_set; + memset(&pdpinfo_set, 0, sizeof(Helios_DataCallStartStruct)); + + pdpinfo_set.ip_type = (int32_t)ip_type; + pdpinfo_set.auth = (int32_t)auth_type; + snprintf(pdpinfo_set.apn, sizeof(pdpinfo_set.apn), "%s", (char *)apninfo.buf); + snprintf(pdpinfo_set.user, sizeof(pdpinfo_set.user), "%s", (char *)usrinfo.buf); + snprintf(pdpinfo_set.pwd, sizeof(pdpinfo_set.pwd), "%s", (char *)pwdinfo.buf); + MP_THREAD_GIL_EXIT(); + #if MICROPY_QPY_MODULE_DSDS + ret = Helios_DataCall_SetPDPContext(net_simid, profile_id, &pdpinfo_set); + #else + ret = Helios_DataCall_SetPDPContext(profile_id, &pdpinfo_set); + #endif + MP_THREAD_GIL_ENTER(); + return mp_obj_new_int(ret); + } + else + { + mp_raise_ValueError(MP_ERROR_TEXT("Incorrect parameter number!")); + } + } +} + +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_net_set_apn_obj, 2, 7, qpy_net_set_apn); + +static mp_obj_t qpy_net_get_apn(size_t n_args, const mp_obj_t *args) +{ +#if defined(PLAT_Qualcomm) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || (defined(PLAT_Unisoc) && !defined(BOARD_EG915UEU_AB)) \ + || defined(PLAT_ASR) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_ASR_1602) || defined(PLAT_Unisoc_8910_R06) + if (n_args == 1) + { + uint8_t net_simid = mp_obj_get_int(args[0]); + int ret = 0; + char apn[99+1] = {0}; + if (net_simid != 0) + { + mp_raise_ValueError(MP_ERROR_TEXT("invalid simid.")); + } + MP_THREAD_GIL_EXIT(); + ret = Helios_Nw_GetApn(apn, net_simid); + MP_THREAD_GIL_ENTER(); + if (ret == 0) + { + return mp_obj_new_str(apn, strlen(apn)); + } + return mp_obj_new_int(-1); + } + else +#endif + { + if (n_args == 2) //pid/simid + { + uint8_t net_simid = mp_obj_get_int(args[1]); + int ret = 0; + uint8_t profile_id = mp_obj_get_int(args[0]); + Helios_DataCallStartStruct pdpinfo_get; + + #if MICROPY_QPY_MODULE_DSDS + if ((net_simid != 0) && (net_simid != 1)) + #else + if (net_simid != 0) + #endif + { + mp_raise_ValueError(MP_ERROR_TEXT("invalid simid.")); + } + + if ((profile_id < HELIOS_PROFILE_IDX_MIN) || (profile_id > HELIOS_PROFILE_IDX_MAX)) + { + mp_raise_ValueError(MP_ERROR_TEXT("invalid profile_id.")); + } + memset(&pdpinfo_get, 0, sizeof(Helios_DataCallStartStruct)); + MP_THREAD_GIL_EXIT(); + #if MICROPY_QPY_MODULE_DSDS + ret = Helios_DataCall_GetPDPContext(net_simid,profile_id, &pdpinfo_get); + #else + ret = Helios_DataCall_GetPDPContext(profile_id, &pdpinfo_get); + #endif + MP_THREAD_GIL_ENTER(); + if (ret != 0) + return mp_obj_new_int(-1); + + mp_obj_t tuple[5] = { + mp_obj_new_int(pdpinfo_get.ip_type), + mp_obj_new_str(pdpinfo_get.apn, strlen(pdpinfo_get.apn)), + mp_obj_new_str(pdpinfo_get.user, strlen(pdpinfo_get.user)), + mp_obj_new_str(pdpinfo_get.pwd, strlen(pdpinfo_get.pwd)), + mp_obj_new_int(pdpinfo_get.auth)}; + + return mp_obj_new_tuple(5, tuple); + } + else + { + mp_raise_ValueError(MP_ERROR_TEXT("Incorrect parameter number!")); + } + } +} + +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_net_get_apn_obj, 1, 2, qpy_net_get_apn); + +#if MICROPY_QPY_MODULE_NET_LED +static mp_obj_t qpy_set_networkled_config( const mp_obj_t args) +{ + + typedef struct network_led_control_info{ + int i_gpio_num; // GPIO_NO + uint32_t i_net_type; // TCP UDP 0-tcp 1-udp + uint32_t i_gpio_low_time; // GPIO LOW times ms + uint32_t i_gpio_hight_time; // GPIO hight times ms + uint32_t i_loop_nums; // cycle nums + }network_led_control_info_t; + + int Helios_NW_Led_Config(network_led_control_info_t config); + volatile network_led_control_info_t config; + mp_obj_t *items = NULL; + size_t len = 0; + char *str = NULL; + mp_obj_list_get(args, &len, &items); + if ( len!= 5){ + return mp_obj_new_int(-1); + } + config.i_gpio_num = (int)mp_obj_get_int(items[0]); + config.i_net_type = (int)mp_obj_get_int(items[1]); + config.i_gpio_low_time =(int) mp_obj_get_int(items[2]); + config.i_gpio_hight_time = (int)mp_obj_get_int(items[3]); + config.i_loop_nums =(int) mp_obj_get_int(items[4]); + MP_THREAD_GIL_EXIT(); + Helios_NW_Led_Config(config); + MP_THREAD_GIL_ENTER(); + return mp_obj_new_int(0); + +} +static MP_DEFINE_CONST_FUN_OBJ_1(qpy_set_networkled_config_obj, qpy_set_networkled_config); +#endif + +static c_callback_t *g_net_user_callback = NULL; + +static void qpy_net_event_handler(uint8_t sim_id, int32_t event_id, void *ctx) +{ + switch (event_id) + { + case HELIOS_NW_DATA_REG_STATUS_IND: + { + Helios_NwRegisterInfoStruct *nw_register_status = (Helios_NwRegisterInfoStruct *)ctx; + + if (g_net_user_callback) + { + QPY_NET_LOG("[net] callback start.\r\n"); + st_CallBack_Net *Net_param = malloc(sizeof(st_CallBack_Net)); + if(NULL != Net_param) + { + Net_param->event_id = event_id; + Net_param->status = nw_register_status->status; + Net_param->lac = nw_register_status->lac; + Net_param->cid = nw_register_status->cid; + Net_param->act = nw_register_status->act; + Net_param->callback = *g_net_user_callback; + QPY_NET_LOG("[net] callback start 1.\r\n"); + qpy_send_msg_to_callback_deal_thread(CALLBACK_TYPE_ID_NET, Net_param); + } + QPY_NET_LOG("[net] callback end.\r\n"); + } + break; + } + #if MICROPY_QPY_MODULE_JAMDET + case HELIOS_NW_JAMMING_DETECT_IND: + { + /* ... */ + QPY_NET_LOG("[net]jamming event.\r\n", event_id); + uint8_t jam_status = *(uint8_t *)ctx; + if (g_net_user_callback) + { + MP_THREAD_GIL_ENTER(); + GC_STACKTOP_SET(); + mp_obj_t tuple[3] = + { + mp_obj_new_int(event_id), + mp_obj_new_int(jam_status), + mp_obj_new_int(sim_id) + }; + mp_sched_schedule_ex(g_net_user_callback, mp_obj_new_tuple(3, tuple)); + GC_STACKTOP_CLEAR(); + MP_THREAD_GIL_EXIT(); + } + break; + } + #endif + case HELIOS_NW_VOICE_REG_STATUS_IND: + /* ... */ + QPY_NET_LOG("[net] ind_flag = %x\r\n", event_id); + break; + case HELIOS_NW_NITZ_TIME_UPDATE_IND: + /* ... */ + QPY_NET_LOG("[net] ind_flag = %x\r\n", event_id); + break; + case HELIOS_NW_SIGNAL_QUALITY_IND: + /* ... */ + QPY_NET_LOG("[net] ind_flag = %x\r\n", event_id); + break; + default: + QPY_NET_LOG("[net] event handler, ind=%x\r\n", event_id); + break; + } +} + +/*=============================================================================*/ +/* FUNCTION: qpy_net_add_event_handler */ +/*=============================================================================*/ +/*!@brief: registered user callback function + * + * @handler [in] callback function + * + * @return: + * 0 - success + * -1 - error + */ +/*=============================================================================*/ +static mp_obj_t qpy_net_add_event_handler(mp_obj_t handler) +{ + static c_callback_t cb = {0}; + memset(&cb, 0, sizeof(c_callback_t)); + cb.arg = mp_obj_new_tuple(5, NULL); + g_net_user_callback = &cb; + mp_sched_schedule_callback_register(g_net_user_callback, handler); + Helios_NwInitStruct info; + memset(&info, 0, sizeof(Helios_NwInitStruct)); + + info.user_cb = qpy_net_event_handler; + Helios_Nw_Init(&info); + return mp_obj_new_int(0); +} +static MP_DEFINE_CONST_FUN_OBJ_1(qpy_net_add_event_handler_obj, qpy_net_add_event_handler); + +/*=============================================================================*/ +/* FUNCTION: qpy_module_net_deinit */ +/*=============================================================================*/ +/*!@brief: deinit net module + * + * + * @return: + * 0 - success + */ +/*=============================================================================*/ +static mp_obj_t qpy_module_net_deinit(void) +{ + QPY_NET_LOG("module net deinit.\r\n"); +#if defined(PLAT_ASR) || defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_Unisoc_8910_R06) + MP_THREAD_GIL_EXIT(); + Helios_Nw_Deinit(); + MP_THREAD_GIL_ENTER(); +#endif + g_net_user_callback = NULL; + return mp_obj_new_int(0); +} +static MP_DEFINE_CONST_FUN_OBJ_0(qpy_module_net_deinit_obj, qpy_module_net_deinit); + +#if MICROPY_QPY_MODULE_FTM_MODE +#include "helios_ftm.h" +#include "helios_os.h" +static mp_obj_t qpy_ftm_mode_switch(mp_obj_t mode) +{ + int ret = -1; + uint8_t ftm_mode = (uint8_t)mp_obj_get_int(mode); + if(ftm_mode > 1) return mp_obj_new_int(-1); + + MP_THREAD_GIL_EXIT(); + if(ftm_mode) + { + ret = Helios_Dev_SetModemFunction(!ftm_mode, 0, 0); + Helios_sleep(1); + ret = (!ret) ? helios_ftm_mode_switch(ftm_mode) : -1; + } + else + { + ret = helios_ftm_mode_switch(ftm_mode); + Helios_sleep(1); + ret = (!ret) ? Helios_Dev_SetModemFunction(!ftm_mode, 0, 0) : -1; + } + MP_THREAD_GIL_ENTER(); + + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_1(qpy_ftm_mode_switch_obj, qpy_ftm_mode_switch); + +static mp_obj_t qpy_ftm_mode_start(mp_obj_t band, mp_obj_t channel, mp_obj_t power) +{ + int ret = -1; + + MP_THREAD_GIL_EXIT(); + ret = helios_ftm_test_start((uint16_t)mp_obj_get_int(band), (uint32_t)mp_obj_get_int(channel), (uint8_t)mp_obj_get_int(power)); + MP_THREAD_GIL_ENTER(); + + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_3(qpy_ftm_mode_start_obj, qpy_ftm_mode_start); + +static mp_obj_t qpy_ftm_mode_stop(void) +{ + int ret = -1; + MP_THREAD_GIL_EXIT(); + //uint16_t band, uint32_t tx_channel,uint8_t tx_power + ret = helios_ftm_test_stop(); + MP_THREAD_GIL_ENTER(); + + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_0(qpy_ftm_mode_stop_obj, qpy_ftm_mode_stop); +#endif + + + +#if MICROPY_QPY_MODULE_BACKCELL + +static mp_obj_t qpy_add_black_cell(size_t n_args, const mp_obj_t *args) +{ + int8_t ret = -1; + uint8_t rat =5; + if (n_args == 2){ + rat = mp_obj_get_int(args[1]); + } + mp_buffer_info_t cell_info = {0}; + mp_get_buffer_raise(args[0], &cell_info, MP_BUFFER_READ); + MP_THREAD_GIL_EXIT(); + ret = Helios_Nw_AddBlackCell(rat, (char *)cell_info.buf); + MP_THREAD_GIL_ENTER(); + if (ret != 0){ + ret =-1; + } + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_add_black_cell_obj, 1, 2, qpy_add_black_cell); + +static mp_obj_t qpy_get_black_cell(void) +{ + int8_t ret = 0; + int8_t i = 0; + mp_obj_t list_gsm = mp_obj_new_list(0, NULL); + mp_obj_t list_lte = mp_obj_new_list(0, NULL); + Helios_NwBackCellInfo info; + memset(&info, 0, sizeof(Helios_NwBackCellInfo)); + MP_THREAD_GIL_EXIT(); + ret = Helios_Nw_GetBlackCell(&info); + MP_THREAD_GIL_ENTER(); + if (ret == 0){ + if (info.gsm_info_num > 0) + { + for (i=0; i 0) + { + for (i=0; i 1) + { + mp_raise_ValueError(MP_ERROR_TEXT("invalid value, blackcellCfg should be in [0,1].")); + } + uint8_t blackcellCfg_num = mp_obj_get_int(args[1]); + if (blackcellCfg_num == 0 || blackcellCfg_num > 8) + { + mp_raise_ValueError(MP_ERROR_TEXT("invalid value, blackcellCfg_num should be in [1,8].")); + } + MP_THREAD_GIL_EXIT(); + ret = Helios_Nw_SetBlackCellCfg(blackcellCfg, blackcellCfg_num); + MP_THREAD_GIL_ENTER(); + if (ret != 0){ + ret =-1; + } + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_set_black_cell_cfg_obj, 2, 2, qpy_set_black_cell_cfg); + +static mp_obj_t qpy_delete_black_cell(size_t n_args, const mp_obj_t *args) +{ + int8_t ret = -1; + if (n_args == 0) + { + ret = Helios_Nw_DeleteAllBlackCell(); + } + else if (n_args == 1) + { + uint8_t rat = 5; + mp_buffer_info_t cell_info = {0}; + mp_get_buffer_raise(args[0], &cell_info, MP_BUFFER_READ); + MP_THREAD_GIL_EXIT(); + ret = Helios_Nw_DeleteBlackCell(rat, (char *)cell_info.buf); + MP_THREAD_GIL_ENTER(); + } + if (ret != 0){ + ret =-1; + } + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_delete_black_cell_obj, 0, 1, qpy_delete_black_cell); +#endif + + +#if MICROPY_QPY_MODULE_DRX_TIMER +static mp_obj_t qpy_net_get_drxtm(void) +{ + uint8_t cur_simid = _get_current_simid(); + uint16_t drx_timer_value = 0; + MP_THREAD_GIL_EXIT(); + if(0 != Helios_Nw_GetDrxtm(cur_simid, &drx_timer_value)) { + MP_THREAD_GIL_ENTER(); + return mp_obj_new_int(-1); + } + MP_THREAD_GIL_ENTER(); + return mp_obj_new_int(drx_timer_value); +} +static MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_drxtm_obj, qpy_net_get_drxtm); + +static mp_obj_t qpy_net_set_drxtm(mp_obj_t drx_timer) +{ + uint8_t cur_simid = _get_current_simid(); + uint16_t drx_timer_value = (uint16_t)mp_obj_get_int(drx_timer); + MP_THREAD_GIL_EXIT(); + if(0 != Helios_Nw_SetDrxtm(cur_simid, drx_timer_value)) { + MP_THREAD_GIL_ENTER(); + return mp_obj_new_int(-1); + } + MP_THREAD_GIL_ENTER(); + return mp_obj_new_int(0); +} +static MP_DEFINE_CONST_FUN_OBJ_1(qpy_net_set_drxtm_obj, qpy_net_set_drxtm); +#endif + +#if MICROPY_QPY_MODULE_JAMDET +static mp_obj_t qpy_jamdet_set_switch(size_t n_args, const mp_obj_t *args) +{ + uint8_t sim_id = 0; + + uint8_t opt = (uint8_t)mp_obj_get_int(args[0]); + if ((opt != 0) && (opt != 1)) + { + mp_raise_ValueError("invalid value, opt shuould be 0 or 1,"); + } + + if (n_args == 2) + { + sim_id = (uint8_t)mp_obj_get_int(args[1]); + if ((sim_id != 0) && (sim_id != 1)) + { + mp_raise_ValueError("invalid value, simId should be 0 or 1."); + } + } + + MP_THREAD_GIL_EXIT(); + int ret = Helios_Nw_SetJamdetSwitch(sim_id, opt); + MP_THREAD_GIL_ENTER(); + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_jamdet_set_switch_obj, 1, 2, qpy_jamdet_set_switch); + +static mp_obj_t qpy_jamdet_get_switch(size_t n_args, const mp_obj_t *args) +{ + uint8_t sim_id = 0; + if (n_args == 1) + { + sim_id = (uint8_t)mp_obj_get_int(args[0]); + if ((sim_id != 0) && (sim_id != 1)) + { + mp_raise_ValueError("invalid value, simId should be 0 or 1."); + } + } + uint8_t opt = 0; + MP_THREAD_GIL_EXIT(); + Helios_Nw_GetJamdetSwitch(sim_id, &opt); + MP_THREAD_GIL_ENTER(); + + return mp_obj_new_int(opt); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_jamdet_get_switch_obj, 0, 1, qpy_jamdet_get_switch); + +static mp_obj_t qpy_jamdet_set_configuration(size_t n_args, const mp_obj_t *args) +{ + uint8_t sim_id = 0; + if (n_args == 8) + { + sim_id = (uint8_t)mp_obj_get_int(args[7]); + if ((sim_id != 0) && (sim_id != 1)) + { + mp_raise_ValueError("invalid value, simId should be 0 or 1."); + } + } + + Helios_NwJamDetConfigStruct cfg = {0}; + cfg.gsm_minch = mp_obj_get_int(args[0]); + cfg.gsm_sinr = mp_obj_get_int(args[1]); + cfg.gsm_rssi = mp_obj_get_int(args[2]); + cfg.lte_rsrp = mp_obj_get_int(args[3]); + cfg.lte_rsrq = mp_obj_get_int(args[4]); + cfg.lte_rssi = mp_obj_get_int(args[5]); + cfg.shake_period = mp_obj_get_int(args[6]); + + if ((cfg.gsm_minch < 0) || (cfg.gsm_minch > 254)) + { + mp_raise_ValueError("invalid value, gsm_minch should be in [0,254]."); + } + if ((cfg.gsm_sinr < 0) || (cfg.gsm_sinr > 63)) + { + mp_raise_ValueError("invalid value, gsm_sinr should be in [0,63]."); + } + if ((cfg.gsm_rssi < -110) || (cfg.gsm_rssi > -50)) + { + mp_raise_ValueError("invalid value, gsm_rssi should be in [-110,-50]."); + } + if ((cfg.lte_rsrp < -140) || (cfg.lte_rsrp > -44)) + { + mp_raise_ValueError("invalid value, lte_rsrp should be in [-140,-44]."); + } + if ((cfg.lte_rsrq < -19) || (cfg.lte_rsrq > -3)) + { + mp_raise_ValueError("invalid value, lte_rsrq should be in [-19,-3]."); + } + if ((cfg.lte_rssi < -120) || (cfg.lte_rssi > -20)) + { + mp_raise_ValueError("invalid value, lte_rssi should be in [-120,-20]."); + } + if ((cfg.shake_period < 1) || (cfg.shake_period > 10)) + { + mp_raise_ValueError("invalid value, shake_period should be in [1,10]."); + } + + MP_THREAD_GIL_EXIT(); + int ret = Helios_Nw_SetJamdetConfiguration(sim_id, &cfg); + MP_THREAD_GIL_ENTER(); + + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_jamdet_set_config_obj, 7, 8, qpy_jamdet_set_configuration); + +static mp_obj_t qpy_jamdet_get_configuration(size_t n_args, const mp_obj_t *args) +{ + uint8_t sim_id = 0; + if (n_args == 1) + { + sim_id = (uint8_t)mp_obj_get_int(args[0]); + if ((sim_id != 0) && (sim_id != 1)) + { + mp_raise_ValueError("invalid value, simId should be 0 or 1."); + } + } + + Helios_NwJamDetConfigStruct cfg = {0}; + MP_THREAD_GIL_EXIT(); + Helios_Nw_GetJamdetConfiguration(sim_id, &cfg); + MP_THREAD_GIL_ENTER(); + mp_obj_t info[7] = + { + mp_obj_new_int(cfg.gsm_minch), + mp_obj_new_int(cfg.gsm_sinr), + mp_obj_new_int(cfg.gsm_rssi), + mp_obj_new_int(cfg.lte_rsrp), + mp_obj_new_int(cfg.lte_rsrq), + mp_obj_new_int(cfg.lte_rssi), + mp_obj_new_int(cfg.shake_period) + }; + return mp_obj_new_tuple(7, info); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_jamdet_get_config_obj, 0, 1, qpy_jamdet_get_configuration); + +static mp_obj_t qpy_jamdet_get_stauts(size_t n_args, const mp_obj_t *args) +{ + uint8_t sim_id = 0; + if (n_args == 1) + { + sim_id = (uint8_t)mp_obj_get_int(args[0]); + if ((sim_id != 0) && (sim_id != 1)) + { + mp_raise_ValueError("invalid value, simId should be 0 or 1."); + } + } + + uint8_t opt = 0; + MP_THREAD_GIL_EXIT(); + Helios_Nw_GetJamdetSwitch(sim_id, &opt); + MP_THREAD_GIL_ENTER(); + if (opt == 0) + { + mp_raise_ValueError("Please enable the jamdet function first."); + } + + uint8_t status = 0; + MP_THREAD_GIL_EXIT(); + int ret = Helios_Nw_GetJamdetStatus(sim_id, &status); + MP_THREAD_GIL_ENTER(); + if (ret == 0) + { + return mp_obj_new_int(status); + } + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_jamdet_get_stauts_obj, 0, 1, qpy_jamdet_get_stauts); + +#endif + +#if defined(MICROPY_QPY_MODULE_IMS_STATUS) +static mp_obj_t qpy_net_get_ims_register(size_t n_args, const mp_obj_t *args) +{ + uint8_t sim_id = _get_current_simid();; + if (n_args == 1) { + sim_id = mp_obj_get_int(args[0]); + } + if ((sim_id != 0) && (sim_id != 1)) + { + mp_raise_ValueError("invalid value, simId should be 0 or 1."); + } + MP_THREAD_GIL_EXIT(); + int ret = Helios_Nw_ImsIsRegister(sim_id); + MP_THREAD_GIL_ENTER(); + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_net_get_ims_register_obj, 0, 1, qpy_net_get_ims_register); +#endif + +#if MICROPY_QPY_MODULE_NET_EX + +static mp_obj_t qpy_net_get_T3402(void) +{ + char resp[128] = {0}; + char para[64] = {0}; + MP_THREAD_GIL_EXIT(); + HELIOS_AT_RESP_STATUS_E ret = Helios_Atcmd_Send_Sync(0, "AT+QCFG=\"emmtimer\"\r\n", resp, sizeof(resp), NULL, 10); + MP_THREAD_GIL_ENTER(); + if(ret == HELIOS_AT_RESP_OK) { + Helios_Atcmd_Get_Para_Value_Str(resp, 1, 1, para, sizeof(para)); + if(strlen(para) != 0) { + return mp_obj_new_str(para, strlen(para)); + } + } + return mp_obj_new_int(-1); +} +static MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_T3402_obj, qpy_net_get_T3402); + + +static mp_obj_t qpy_net_get_T3412(void) +{ + char resp[128] = {0}; + char para[64] = {0}; + MP_THREAD_GIL_EXIT(); + HELIOS_AT_RESP_STATUS_E ret = Helios_Atcmd_Send_Sync(0, "AT+QCFG=\"emmtimer\"\r\n", resp, sizeof(resp), NULL, 10); + MP_THREAD_GIL_ENTER(); + if(ret == HELIOS_AT_RESP_OK) { + Helios_Atcmd_Get_Para_Value_Str(resp, 1, 2, para, sizeof(para)); + if(strlen(para) != 0) { + return mp_obj_new_str(para, strlen(para)); + } + } + return mp_obj_new_int(-1); +} +static MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_T3412_obj, qpy_net_get_T3412); + + +static mp_obj_t qpy_net_get_T3324(void) +{ + char resp[128] = {0}; + char para[64] = {0}; + char cmd[64] = {0}; + int n = 0; + HELIOS_AT_RESP_STATUS_E ret = HELIOS_AT_RESP_OK; + MP_THREAD_GIL_EXIT(); + ret = Helios_Atcmd_Send_Sync(0, "AT+CEREG?\r\n", resp, sizeof(resp), NULL, 10); + MP_THREAD_GIL_ENTER(); + if(ret != HELIOS_AT_RESP_OK) { + return mp_obj_new_int(-1); + } + Helios_Atcmd_Get_Para_Value_Str(resp, 1, 0, para, sizeof(para)); + if(strlen(para) != 0) { + n = atoi(para); + } + memset(resp, 0 ,sizeof(resp)); + memset(para, 0 ,sizeof(para)); + if (n !=4) { + MP_THREAD_GIL_EXIT(); + ret = Helios_Atcmd_Send_Sync(0, "AT+CEREG=4\r\n", NULL, 0, NULL, 10); + MP_THREAD_GIL_ENTER(); + if(ret != HELIOS_AT_RESP_OK) { + return mp_obj_new_int(-1); + } + }else { + Helios_Atcmd_Get_Para_Value_Str(resp, 1, 7, para, sizeof(para)); + if(strlen(para) != 0) { + return mp_obj_new_str(para, strlen(para)); + } + } + MP_THREAD_GIL_EXIT(); + Helios_Atcmd_Send_Sync(0, "AT+CEREG?\r\n", resp, sizeof(resp), NULL, 10); + MP_THREAD_GIL_ENTER(); + Helios_Atcmd_Get_Para_Value_Str(resp, 1, 7, para, sizeof(para)); + snprintf(cmd, 64, "AT+CEREG=%d\r\n", n); + MP_THREAD_GIL_EXIT(); + ret = Helios_Atcmd_Send_Sync(0, cmd, NULL, 0, NULL, 10); + MP_THREAD_GIL_ENTER(); + if(ret != HELIOS_AT_RESP_OK) { + return mp_obj_new_int(-1); + } + return mp_obj_new_str(para, strlen(para)); + +} +static MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_T3324_obj, qpy_net_get_T3324); + + +static mp_obj_t qpy_net_get_TeDRX(void) +{ + char resp[128] = {0}; + char para[64] = {0}; + MP_THREAD_GIL_EXIT(); + HELIOS_AT_RESP_STATUS_E ret = Helios_Atcmd_Send_Sync(0, "AT+CEDRXRDP\r\n", resp, sizeof(resp), NULL, 10); + MP_THREAD_GIL_ENTER(); + if(ret == HELIOS_AT_RESP_OK) { + Helios_Atcmd_Get_Para_Value_Str(resp, 1, 1, para, sizeof(para)); + return mp_obj_new_str(para, strlen(para)); + } + return mp_obj_new_int(-1); +} +static MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_TeDRX_obj, qpy_net_get_TeDRX); + +static mp_obj_t qpy_net_get_TPTW(void) +{ + char resp[128] = {0}; + char para[64] = {0}; + MP_THREAD_GIL_EXIT(); + HELIOS_AT_RESP_STATUS_E ret = Helios_Atcmd_Send_Sync(0, "AT+CEDRXRDP\r\n", resp, sizeof(resp), NULL, 10); + MP_THREAD_GIL_ENTER(); + if(ret == HELIOS_AT_RESP_OK) { + Helios_Atcmd_Get_Para_Value_Str(resp, 1, 3, para, sizeof(para)); + return mp_obj_new_str(para, strlen(para)); + } + return mp_obj_new_int(-1); +} +static MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_TPTW_obj, qpy_net_get_TPTW); + +static mp_obj_t qpy_net_get_qRxlevMin(void) +{ + char resp[256] = {0}; + char para[64] = {0}; + MP_THREAD_GIL_EXIT(); + HELIOS_AT_RESP_STATUS_E ret = Helios_Atcmd_Send_Sync(0, "AT+QCFG=\"sibinfo\"\r\n", resp, sizeof(resp), NULL, 10); + MP_THREAD_GIL_ENTER(); + if(ret == HELIOS_AT_RESP_OK) { + Helios_Atcmd_Get_Para_Value_Str(resp, 1, 3, para, sizeof(para)); + if(strlen(para) != 0) { + return mp_obj_new_str(para, strlen(para)); + } + } + return mp_obj_new_int(-1); +} +static MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_qRxlevMin_obj, qpy_net_get_qRxlevMin); + +static mp_obj_t qpy_net_get_reject_cause(void) +{ + char resp[128] = {0}; + char para[64] = {0}; + MP_THREAD_GIL_EXIT(); + HELIOS_AT_RESP_STATUS_E ret = Helios_Atcmd_Send_Sync(0, "AT+QCFG=\"emmcause\"\r\n", resp, sizeof(resp), NULL, 10); + MP_THREAD_GIL_ENTER(); + if(ret == HELIOS_AT_RESP_OK) { + Helios_Atcmd_Get_Para_Value_Str(resp, 1, 1, para, sizeof(para)); + return mp_obj_new_str(para, strlen(para)); + } + return mp_obj_new_int(-1); +} +static MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_reject_cause_obj, qpy_net_get_reject_cause); +#endif + + +static const mp_rom_map_elem_t net_module_globals_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_net) }, + { MP_ROM_QSTR(MP_QSTR___qpy_module_deinit__), MP_ROM_PTR(&qpy_module_net_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_csqQueryPoll), MP_ROM_PTR(&qpy_net_get_csq_obj) }, + { MP_ROM_QSTR(MP_QSTR_getState), MP_ROM_PTR(&qpy_net_get_reg_status_obj) }, + { MP_ROM_QSTR(MP_QSTR_getConfig), MP_ROM_PTR(&qpy_net_get_configuration_obj) }, + { MP_ROM_QSTR(MP_QSTR_setConfig), MP_ROM_PTR(&qpy_net_set_configuration_obj) }, + { MP_ROM_QSTR(MP_QSTR_nitzTime), MP_ROM_PTR(&qpy_net_get_nitz_time_obj) }, + { MP_ROM_QSTR(MP_QSTR_operatorName), MP_ROM_PTR(&qpy_net_get_operator_name_obj) }, + //{ MP_ROM_QSTR(MP_QSTR_setNetMode), MP_ROM_PTR(&qpy_net_set_selection_obj) }, + { MP_ROM_QSTR(MP_QSTR_getNetMode), MP_ROM_PTR(&qpy_net_get_selection_obj) }, + { MP_ROM_QSTR(MP_QSTR_getSignal), MP_ROM_PTR(&qpy_net_get_signal_strength_obj)}, + { MP_ROM_QSTR(MP_QSTR_getCellInfo), MP_ROM_PTR(&qpy_net_get_cell_info_obj) }, + { MP_ROM_QSTR(MP_QSTR_getCellInfos), MP_ROM_PTR(&qpy_net_get_cell_info_v2_obj) }, + + { MP_ROM_QSTR(MP_QSTR_getCi), MP_ROM_PTR(&qpy_net_get_cid_obj) }, + { MP_ROM_QSTR(MP_QSTR_getLac), MP_ROM_PTR(&qpy_net_get_lac_obj) }, + { MP_ROM_QSTR(MP_QSTR_getMnc), MP_ROM_PTR(&qpy_net_get_mnc_obj) }, + { MP_ROM_QSTR(MP_QSTR_getMcc), MP_ROM_PTR(&qpy_net_get_mcc_obj) }, + { MP_ROM_QSTR(MP_QSTR_setModemFun), MP_ROM_PTR(&qpy_net_set_modem_fun_obj) }, + { MP_ROM_QSTR(MP_QSTR_getModemFun), MP_ROM_PTR(&qpy_net_get_modem_fun_obj) }, + { MP_ROM_QSTR(MP_QSTR_setCallback), MP_ROM_PTR(&qpy_net_add_event_handler_obj) }, + + { MP_ROM_QSTR(MP_QSTR_setApn), MP_ROM_PTR(&qpy_net_set_apn_obj) }, + { MP_ROM_QSTR(MP_QSTR_getApn), MP_ROM_PTR(&qpy_net_get_apn_obj) }, + #if MICROPY_QPY_MODULE_NET_LED + { MP_ROM_QSTR(MP_QSTR_set_networkled_config), MP_ROM_PTR(&qpy_set_networkled_config_obj) }, + #endif + { MP_ROM_QSTR(MP_QSTR_getServingCi), MP_ROM_PTR(&qpy_net_get_cid_servingcell_obj) }, + { MP_ROM_QSTR(MP_QSTR_getServingLac), MP_ROM_PTR(&qpy_net_get_lac_servingcell_obj) }, + { MP_ROM_QSTR(MP_QSTR_getServingMnc), MP_ROM_PTR(&qpy_net_get_mnc_servingcell_obj) }, + { MP_ROM_QSTR(MP_QSTR_getServingMcc), MP_ROM_PTR(&qpy_net_get_mcc_servingcell_obj) }, +#if defined(PLAT_Qualcomm) || defined(PLAT_ASR)|| MICROPY_QPY_MODULE_NET_BAND + { MP_ROM_QSTR(MP_QSTR_setBand), MP_ROM_PTR(&qpy_net_set_band_obj) }, + { MP_ROM_QSTR(MP_QSTR_getBand), MP_ROM_PTR(&qpy_net_get_band_obj) }, +#endif +#if defined(PLAT_ASR) || MICROPY_QPY_MODULE_NET_BAND + { MP_ROM_QSTR(MP_QSTR_bandRst), MP_ROM_PTR(&qpy_net_band_restore_obj) }, +#endif + +#if MICROPY_QPY_MODULE_FTM_MODE + { MP_ROM_QSTR(MP_QSTR_ftmModeSwitch), MP_ROM_PTR(&qpy_ftm_mode_switch_obj) }, + { MP_ROM_QSTR(MP_QSTR_ftmTestStart), MP_ROM_PTR(&qpy_ftm_mode_start_obj) }, + { MP_ROM_QSTR(MP_QSTR_ftmTestStop), MP_ROM_PTR(&qpy_ftm_mode_stop_obj) }, +#endif + +#if MICROPY_QPY_MODULE_BACKCELL + { MP_ROM_QSTR(MP_QSTR_addBlackCell), MP_ROM_PTR(&qpy_add_black_cell_obj) }, + { MP_ROM_QSTR(MP_QSTR_getBlackCell), MP_ROM_PTR(&qpy_get_black_cell_obj) }, + { MP_ROM_QSTR(MP_QSTR_getBlackCellCfg), MP_ROM_PTR(&qpy_get_black_cell_cfg_obj) }, + { MP_ROM_QSTR(MP_QSTR_setBlackCellCfg), MP_ROM_PTR(&qpy_set_black_cell_cfg_obj) }, + { MP_ROM_QSTR(MP_QSTR_deleteBlackCell), MP_ROM_PTR(&qpy_delete_black_cell_obj) }, +#endif + +#if MICROPY_QPY_MODULE_DRX_TIMER + { MP_ROM_QSTR(MP_QSTR_setDrxTm), MP_ROM_PTR(&qpy_net_set_drxtm_obj) }, + { MP_ROM_QSTR(MP_QSTR_getDrxTm), MP_ROM_PTR(&qpy_net_get_drxtm_obj) }, +#endif + +#if MICROPY_QPY_MODULE_JAMDET + { MP_ROM_QSTR(MP_QSTR_setJamdetSwitch), MP_ROM_PTR(&qpy_jamdet_set_switch_obj) }, + { MP_ROM_QSTR(MP_QSTR_getJamdetSwitch), MP_ROM_PTR(&qpy_jamdet_get_switch_obj) }, + { MP_ROM_QSTR(MP_QSTR_setJamdetParam), MP_ROM_PTR(&qpy_jamdet_set_config_obj) }, + { MP_ROM_QSTR(MP_QSTR_getJamdetParam), MP_ROM_PTR(&qpy_jamdet_get_config_obj) }, + { MP_ROM_QSTR(MP_QSTR_getJamdetStatus), MP_ROM_PTR(&qpy_jamdet_get_stauts_obj) }, +#endif + +#if defined(MICROPY_QPY_MODULE_IMS_STATUS) + { MP_ROM_QSTR(MP_QSTR_getImsRegister), MP_ROM_PTR(&qpy_net_get_ims_register_obj) }, +#endif + +#if MICROPY_QPY_MODULE_NET_EX + { MP_ROM_QSTR(MP_QSTR_getT3402), MP_ROM_PTR(&qpy_net_get_T3402_obj) }, + { MP_ROM_QSTR(MP_QSTR_getT3412), MP_ROM_PTR(&qpy_net_get_T3412_obj) }, + { MP_ROM_QSTR(MP_QSTR_getT3324), MP_ROM_PTR(&qpy_net_get_T3324_obj) }, + { MP_ROM_QSTR(MP_QSTR_getTeDRX), MP_ROM_PTR(&qpy_net_get_TeDRX_obj) }, + { MP_ROM_QSTR(MP_QSTR_getTPTW), MP_ROM_PTR(&qpy_net_get_TPTW_obj) }, + { MP_ROM_QSTR(MP_QSTR_getqRxlevMin), MP_ROM_PTR(&qpy_net_get_qRxlevMin_obj) }, + { MP_ROM_QSTR(MP_QSTR_getRejectCause), MP_ROM_PTR(&qpy_net_get_reject_cause_obj) }, +#endif +}; + +static MP_DEFINE_CONST_DICT(net_module_globals, net_module_globals_table); +const mp_obj_module_t mp_module_net = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&net_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_net, mp_module_net); +#endif /* MICROPY_QPY_MODULE_NET */ diff --git a/ports/quectel/modostimer.c b/ports/quectel/modostimer.c new file mode 100644 index 0000000000000..8fcce2a3f4c86 --- /dev/null +++ b/ports/quectel/modostimer.c @@ -0,0 +1,167 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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 +#include "py/compile.h" +#include "py/nlr.h" +#include "py/objlist.h" +#include "py/objstr.h" +#include "py/runtime.h" +#include "py/mperrno.h" +#include "py/mphal.h" +#include "py/stream.h" +#include "py/obj.h" + +#if MICROPY_QPY_MODULE_OSTIMER + +#include "helios_os.h" +#include "helios_debug.h" + +#define HELIOS_OSTIMER_LOG(msg, ...) custom_log("osTimer", msg, ##__VA_ARGS__) + + +typedef struct _mod_ostimer_obj_t +{ + mp_obj_base_t base; + Helios_OSTimer_t handle; /* OS supplied timer reference */ + unsigned int initialTime; /* initial expiration time in ms */ + bool cyclicalEn; /* wether to enable the cyclical mode or not */ + c_callback_t callback; /* timer call-back routine */ + bool deleteFlagh; +} mod_ostimer_obj_t; + +const mp_obj_type_t mp_ostimer_type; + +STATIC void mod_ostimer_isr(void *cb) { + c_callback_t *callback = (c_callback_t *)cb; + if(NULL != callback){ + mp_sched_schedule_ex(callback, mp_const_none); + } +} + + +STATIC mp_obj_t mod_ostimer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) +{ + mod_ostimer_obj_t *timer = mp_obj_malloc_with_finaliser(mod_ostimer_obj_t); + + timer->base.type = &mp_ostimer_type; + timer->handle = Helios_OSTimer_Create(); + timer->deleteFlagh = 0; + + return MP_OBJ_FROM_PTR(timer); +} + + +STATIC mp_obj_t mod_ostimer_start(uint n_args, const mp_obj_t *args) +{ + int ret = 0; + + mod_ostimer_obj_t *self = MP_OBJ_TO_PTR(args[0]); + + if (!(self->deleteFlagh)) + { + self->initialTime = mp_obj_get_int(args[1]); + + self->cyclicalEn = !!mp_obj_get_int(args[2]); + + //self->callback = args[3]; + mp_sched_schedule_callback_register(&self->callback, args[3]); + + Helios_OSTimerAttr OSTimerAttr = { + .ms = (uint32_t)self->initialTime, + .cycle_enable = self->cyclicalEn, + .cb = mod_ostimer_isr, + .argv = (void *)&self->callback + }; + ret = Helios_OSTimer_Start(self->handle, &OSTimerAttr); + } + else + { + ret = -1; + } + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_ostimer_start_obj, 3, 5, mod_ostimer_start); + +STATIC mp_obj_t mod_ostimer_stop(mp_obj_t arg0) +{ + int ret = 0; + + mod_ostimer_obj_t *self = MP_OBJ_TO_PTR(arg0); + if (!(self->deleteFlagh)) + { + ret = Helios_OSTimer_Stop(self->handle); + } + else + { + ret = -1; + } + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ostimer_stop_obj, mod_ostimer_stop); + + + +STATIC mp_obj_t mod_ostimer_delete(mp_obj_t arg0) +{ + int ret = 0; + + mod_ostimer_obj_t *self = MP_OBJ_TO_PTR(arg0); + + if (!(self->deleteFlagh)) + { + self->deleteFlagh = 1; + Helios_OSTimer_Delete(self->handle); + HELIOS_OSTIMER_LOG("[osTimer] ostimer delete\r\n"); + } + + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ostimer_delete_obj, mod_ostimer_delete); + + +STATIC const mp_rom_map_elem_t mod_ostimer_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_osTimer) }, + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_ostimer_delete_obj) }, + { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&mod_ostimer_start_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&mod_ostimer_stop_obj) }, + { MP_ROM_QSTR(MP_QSTR_delete_timer), MP_ROM_PTR(&mod_ostimer_delete_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(mod_ostimer_locals_dict, mod_ostimer_locals_dict_table); + + +const mp_obj_type_t mp_ostimer_type = { + { &mp_type_type }, + .name = MP_QSTR_osTimer, + .make_new = mod_ostimer_make_new, + .locals_dict = (mp_obj_dict_t *)&mod_ostimer_locals_dict, +}; + + +#endif /* MICROPY_QPY_MODULE_OSTIMER */ diff --git a/ports/quectel/modsim.c b/ports/quectel/modsim.c new file mode 100644 index 0000000000000..691d7ab02b5d3 --- /dev/null +++ b/ports/quectel/modsim.c @@ -0,0 +1,1128 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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 "stdio.h" +#include "stdlib.h" +#include "obj.h" +#include "runtime.h" +#include "mphalport.h" + +#if MICROPY_QPY_MODULE_SIM + +#include "helios_debug.h" +#include "helios_sim.h" + +#if MICROPY_QPY_MODULE_ESIM_SIM_SWITCH +#include "rt_lpa.h" +#include "rt_port_at.h" +#include "rt_utils.h" + +#define MAX_EID_HEX_LEN 16 +#define MAX_EID_LEN 33 +#define THE_MAX_CARD_NUM 20 +#endif + +#define QPY_MODSIM_LOG(msg, ...) custom_log("SIM", msg, ##__VA_ARGS__) + + +static void toUpperCase(char *str) +{ + while (*str != '\0') { + if(*str >='a' && *str <= 'z') { + *str -= 32; + } + str++; + } +} + +int _get_current_simid(void) +{ + int cur_simid = 0; + +#if defined(PLAT_ASR) ||defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_Unisoc_8850_R02) || defined(PLAT_EIGEN) || defined(PLAT_ASR_1602) || defined(PLAT_EIGEN_718) + + uint8_t sim_id = 0; + MP_THREAD_GIL_EXIT(); + Helios_SIM_GetCurrentSimid(&sim_id); + MP_THREAD_GIL_ENTER(); + cur_simid = sim_id; +#elif defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) + cur_simid = 0; +#endif + + if(cur_simid < 0) + { + cur_simid = 0; + } + + return cur_simid; +} +/*=============================================================================*/ +/* FUNCTION: qpy_sim_get_imsi */ +/*=============================================================================*/ +/*!@brief: Get the IMSI of the SIM card + * + * @return: + * if get successfully, return the IMSI + * -1 - error + */ +/*=============================================================================*/ +static mp_obj_t qpy_sim_get_imsi(size_t n_args, const mp_obj_t *args) +{ + int cur_simid = 0; + char imsi_str[HELIOS_SIM_IMSI_LEN+1] = {0}; + uint8_t status = 0; + int ret = 0; + if ( n_args > 0 ) + { + cur_simid = mp_obj_get_int(args[0]); + }else{ + cur_simid = _get_current_simid(); + } + if ((cur_simid != 0) && (cur_simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); + } + MP_THREAD_GIL_EXIT(); + Helios_SIM_GetCardStatus(cur_simid, (Helios_SIM_Status_e *)&status); + MP_THREAD_GIL_ENTER(); + if (ret == 0) + { + if (status != 1) + { + return mp_obj_new_int(-1); + } + } + else + { + return mp_obj_new_int(-1); + } + MP_THREAD_GIL_EXIT(); + ret = Helios_SIM_GetIMSI(cur_simid, (void *)imsi_str, sizeof(imsi_str)); + MP_THREAD_GIL_ENTER(); + if (ret == 0) + { + return mp_obj_new_str(imsi_str, strlen(imsi_str)); + } + + return mp_obj_new_int(-1); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_sim_get_imsi_obj, 0, 1, qpy_sim_get_imsi); + + +/*=============================================================================*/ +/* FUNCTION: qpy_sim_get_iccid */ +/*=============================================================================*/ +/*!@brief: Get the ICCID of the SIM card + * + * @return: + * if get successfully, return the ICCID + * -1 - error + */ +/*=============================================================================*/ +static mp_obj_t qpy_sim_get_iccid(size_t n_args, const mp_obj_t *args) +{ + char iccid_str[HELIOS_SIM_ICCID_LEN+1] = {0}; + uint8_t status = 0; + int ret = 0; + int cur_simid = 0; + if ( n_args > 0 ) + { + cur_simid = mp_obj_get_int(args[0]); + }else{ + cur_simid = _get_current_simid(); + } + if ((cur_simid != 0) && (cur_simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); + } + MP_THREAD_GIL_EXIT(); + Helios_SIM_GetCardStatus(cur_simid, (Helios_SIM_Status_e *)&status); + MP_THREAD_GIL_ENTER(); + if (ret == 0) + { + if (status != 1) + { + return mp_obj_new_int(-1); + } + } + else + { + return mp_obj_new_int(-1); + } + MP_THREAD_GIL_EXIT(); + ret = Helios_SIM_GetICCID(cur_simid, (void *)iccid_str, sizeof(iccid_str)); + MP_THREAD_GIL_ENTER(); + if (ret == 0) + { + toUpperCase(iccid_str); + return mp_obj_new_str(iccid_str, strlen(iccid_str)); + } + + return mp_obj_new_int(-1); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_sim_get_iccid_obj, 0, 1, qpy_sim_get_iccid); + + +/*=============================================================================*/ +/* FUNCTION: qpy_sim_get_phonenumber */ +/*=============================================================================*/ +/*!@brief: Get the phone number of the SIM card + * + * @return: + * if get successfully, return the phone number + * -1 - error + */ +/*=============================================================================*/ +static mp_obj_t qpy_sim_get_phonenumber(size_t n_args, const mp_obj_t *args) +{ + char phone_number[HELIOS_SIM_PHONENUM_LEN+1] = {0}; + int ret = 0; + int cur_simid = 0; + if ( n_args > 0 ) + { + cur_simid = mp_obj_get_int(args[0]); + }else{ + cur_simid = _get_current_simid(); + } + if ((cur_simid != 0) && (cur_simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); + } + MP_THREAD_GIL_EXIT(); + ret = Helios_SIM_GetPhoneNumber(cur_simid, (void *)phone_number, sizeof(phone_number)); + MP_THREAD_GIL_ENTER(); + if (ret == 0) + { + return mp_obj_new_str(phone_number, strlen(phone_number)); + } + + return mp_obj_new_int(-1); +} + +#if !defined (PLAT_RDA) +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_sim_get_phonenumber_obj, 0, 1, qpy_sim_get_phonenumber); +#endif +/*=============================================================================*/ +/* FUNCTION: qpy_sim_enable_pin */ +/*=============================================================================*/ +/*!@brief: enable SIM card PIN code verification, and restart will take effect + * + * @pin [in] PIN code + * @return: + * 0 - success + * -1 - error + */ +/*=============================================================================*/ +#ifndef MICROPY_QPY_MODULE_NO_SIMPIN +static mp_obj_t qpy_sim_enable_pin(size_t n_args, const mp_obj_t *args) +{ + Helios_SIMPinInfoStruct info = {0}; + mp_buffer_info_t bufinfo = {0}; + int cur_simid = 0; + if ( n_args > 1 ) + { + cur_simid = mp_obj_get_int(args[1]); + }else{ + cur_simid = _get_current_simid(); + } + if ((cur_simid != 0) && (cur_simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); + } + mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ); + if (bufinfo.len > HELIOS_SIM_PIN_LEN_MAX) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, the length of pin should be no more than [%d] bytes."), HELIOS_SIM_PIN_LEN_MAX); + } + + strncpy((char *)info.pin, (const char *)bufinfo.buf, bufinfo.len); + + + MP_THREAD_GIL_EXIT(); + int ret = Helios_SIM_PINEnable(cur_simid, &info); + MP_THREAD_GIL_ENTER(); + if (ret == 0) + { + return mp_obj_new_int(ret); + } + + return mp_obj_new_int(-1); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_sim_enable_pin_obj, 1, 2, qpy_sim_enable_pin); + + +/*=============================================================================*/ +/* FUNCTION: qpy_sim_disable_pin */ +/*=============================================================================*/ +/*!@brief: disable SIM card PIN code verification + * + * @pin [in] PIN code + * @return: + * 0 - success + * -1 - error + */ +/*=============================================================================*/ +static mp_obj_t qpy_sim_disable_pin(size_t n_args, const mp_obj_t *args) +{ + Helios_SIMPinInfoStruct info = {0}; + mp_buffer_info_t bufinfo = {0}; + int cur_simid = 0; + if ( n_args > 1 ) + { + cur_simid = mp_obj_get_int(args[1]); + }else{ + cur_simid = _get_current_simid(); + } + + mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ); + if (bufinfo.len > HELIOS_SIM_PIN_LEN_MAX) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, the length of pin should be no more than [%d] bytes."), HELIOS_SIM_PIN_LEN_MAX); + } + if ((cur_simid != 0) && (cur_simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); + } + strncpy((char *)info.pin, (const char *)bufinfo.buf, bufinfo.len); + + MP_THREAD_GIL_EXIT(); + int ret = Helios_SIM_PINDisable(cur_simid, &info); + MP_THREAD_GIL_ENTER(); + if (ret == 0) + { + return mp_obj_new_int(ret); + } + + return mp_obj_new_int(-1); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_sim_disable_pin_obj, 1, 2, qpy_sim_disable_pin); + + +/*=============================================================================*/ +/* FUNCTION: qpy_sim_verify_pin */ +/*=============================================================================*/ +/*!@brief: when the SIM state is requested PIN/PIN2, enter the PIN/PIN2 code to verify + * + * @pin [in] PIN code + * @return: + * 0 - success + * -1 - error + */ +/*=============================================================================*/ +static mp_obj_t qpy_sim_verify_pin(size_t n_args, const mp_obj_t *args) +{ + Helios_SIMPinInfoStruct info = {0}; + mp_buffer_info_t bufinfo = {0}; + int cur_simid = 0; + if ( n_args > 1 ) + { + cur_simid = mp_obj_get_int(args[1]); + }else{ + cur_simid = _get_current_simid(); + } + mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ); + + if (bufinfo.len > HELIOS_SIM_PIN_LEN_MAX) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, the length of pin should be no more than [%d] bytes."), HELIOS_SIM_PIN_LEN_MAX); + } + if ((cur_simid != 0) && (cur_simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); + } + strncpy((char *)info.pin, (const char *)bufinfo.buf, bufinfo.len); + + MP_THREAD_GIL_EXIT(); + int ret = Helios_SIM_PINVerify(cur_simid, &info); + MP_THREAD_GIL_ENTER(); + if (ret == 0) + { + return mp_obj_new_int(ret); + } + + return mp_obj_new_int(-1); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_sim_verify_pin_obj, 1, 2,qpy_sim_verify_pin); + +/*=============================================================================*/ +/* FUNCTION: qpy_sim_change_pin */ +/*=============================================================================*/ +/*!@brief: After enabling SIM card PIN verification, change the SIM card PIN + * + * @old_pin [in] old PIN + * @new_pin [in] new PIN + * @return: + * 0 - success + * -1 - error + */ +/*=============================================================================*/ + +static mp_obj_t qpy_sim_change_pin(size_t n_args, const mp_obj_t *args) +{ + Helios_SIMChangePinInfoStruct info = {0}; + mp_buffer_info_t bufinfo[2] = {0}; + int cur_simid = 0; + if ( n_args > 2 ) + { + cur_simid = mp_obj_get_int(args[2]); + }else{ + cur_simid = _get_current_simid(); + } + mp_get_buffer_raise(args[0], &bufinfo[0], MP_BUFFER_READ); + mp_get_buffer_raise(args[1], &bufinfo[1], MP_BUFFER_READ); + + if ((bufinfo[0].len > HELIOS_SIM_PIN_LEN_MAX) || (bufinfo[1].len > HELIOS_SIM_PIN_LEN_MAX)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, the length of pin should be no more than [%d] bytes."), HELIOS_SIM_PIN_LEN_MAX); + } + if ((cur_simid != 0) && (cur_simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); + } + strncpy((char *)info.old_pin, (const char *)bufinfo[0].buf, bufinfo[0].len); + strncpy((char *)info.new_pin, (const char *)bufinfo[1].buf, bufinfo[1].len); + + MP_THREAD_GIL_EXIT(); + int ret = Helios_SIM_PINChange(cur_simid, &info); + MP_THREAD_GIL_ENTER(); + if (ret == 0) + { + return mp_obj_new_int(ret); + } + + return mp_obj_new_int(-1); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_sim_change_pin_obj, 2,3,qpy_sim_change_pin); + + +/*=============================================================================*/ +/* FUNCTION: qpy_sim_unblock_pin */ +/*=============================================================================*/ +/*!@brief: When the SIM card status is requested PUK/PUK2 after multiple incorrect input + * of PIN/PIN2 code, input PUK/PUK2 code and a new PIN/PIN2 code to unlock + * + * @puk [in] PUK/PUK2 + * @new_pin [in] new PIN/PIN2 + * @return: + * 0 - success + * -1 - error + */ +/*=============================================================================*/ +static mp_obj_t qpy_sim_unblock_pin(size_t n_args, const mp_obj_t *args) +{ + Helios_SIMUnlockPinInfoStruct info = {0}; + mp_buffer_info_t bufinfo[2] = {0}; + + int cur_simid = 0; + if ( n_args > 2 ) + { + cur_simid = mp_obj_get_int(args[2]); + }else{ + cur_simid = _get_current_simid(); + + } + mp_get_buffer_raise(args[0], &bufinfo[0], MP_BUFFER_READ); + + + mp_get_buffer_raise(args[1], &bufinfo[1], MP_BUFFER_READ); + + + if ((bufinfo[0].len > HELIOS_SIM_PIN_LEN_MAX) || (bufinfo[1].len > HELIOS_SIM_PIN_LEN_MAX)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, the length of pin or puk should be no more than [%d] bytes."), HELIOS_SIM_PIN_LEN_MAX); + } + if ((cur_simid != 0) && (cur_simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); + } + strncpy((char *)info.puk, (const char *)bufinfo[0].buf, bufinfo[0].len); + strncpy((char *)info.new_pin, (const char *)bufinfo[1].buf, bufinfo[1].len); + + MP_THREAD_GIL_EXIT(); + int ret = Helios_SIM_PINUnlock(cur_simid, &info); + MP_THREAD_GIL_ENTER(); + if (ret == 0) + { + return mp_obj_new_int(ret); + } + + return mp_obj_new_int(-1); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_sim_unblock_pin_obj, 2, 3, qpy_sim_unblock_pin); +#endif + +#if MICROPY_QPY_MODULE_PIN_REMATTEMPTS + +static mp_obj_t qpy_sim_pin_remain_attempts(size_t n_args, const mp_obj_t *args) +{ + Helios_SIMRemainPinAttempts info = {0}; + + uint8_t cur_simid = _get_current_simid(); + MP_THREAD_GIL_EXIT(); + int ret = Helios_SIM_PINRemainAttempts(cur_simid, &info); + MP_THREAD_GIL_ENTER(); + if (ret == 0) + { + if (n_args > 0) + { + int flag = mp_obj_get_int(args[0]); + if (flag == 0) + { + mp_obj_t tuple[2] = { + mp_obj_new_int(info.pin_remain_attempts), + mp_obj_new_int(info.puk_remain_attempts) + }; + return mp_obj_new_tuple(2, tuple); + } + else if (flag == 1) + { + mp_obj_t tuple[4] = { + mp_obj_new_int(info.pin_remain_attempts), + mp_obj_new_int(info.puk_remain_attempts), + mp_obj_new_int(info.pin2_remain_attempts), + mp_obj_new_int(info.puk2_remain_attempts) + }; + return mp_obj_new_tuple(4, tuple); + } + else + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, flag should be in [0,1].")); + } + } + else + { + mp_obj_t tuple[2] = { + mp_obj_new_int(info.pin_remain_attempts), + mp_obj_new_int(info.puk_remain_attempts) + }; + return mp_obj_new_tuple(2, tuple); + } + } + return mp_obj_new_int(-1); + +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_sim_pin_remain_attempts_obj, 0, 1, qpy_sim_pin_remain_attempts); + +#endif +/*=============================================================================*/ +/* FUNCTION: sim_get_card_status */ +/*=============================================================================*/ +/*!@brief: Get the status of the SIM card. + * + * @return : + * - 0 SIM was removed. + * - 1 SIM is ready. + * - 2 Expecting the universal PIN./SIM is locked, waiting for a CHV1 password. + * - 3 Expecting code to unblock the universal PIN./SIM is blocked, CHV1 unblocking password is required. + * - 4 SIM is locked due to a SIM/USIM personalization check failure. + * - 5 SIM is blocked due to an incorrect PCK; an MEP unblocking password is required. + * - 6 Expecting key for hidden phone book entries. + * - 7 Expecting code to unblock the hidden key. + * - 8 SIM is locked; waiting for a CHV2 password. + * - 9 SIM is blocked; CHV2 unblocking password is required. + * - 10 SIM is locked due to a network personalization check failure. + * - 11 SIM is blocked due to an incorrect NCK; an MEP unblocking password is required. + * - 12 +SIM is locked due to a network subset personalization check failure. + * - 13 SIM is blocked due to an incorrect NSCK; an MEP unblocking password is required. + * - 14 SIM is locked due to a service provider personalization check failure. + * - 15 SIM is blocked due to an incorrect SPCK; an MEP unblocking password is required. + * - 16 SIM is locked due to a corporate personalization check failure. + * - 17 SIM is blocked due to an incorrect CCK; an MEP unblocking password is required. + * - 18 SIM is being initialized; waiting for completion. + * - 19 Use of CHV1/CHV2/universal PIN/code to unblock the CHV1/code to unblock the CHV2/code to unblock the universal PIN/ is blocked. + * - 20 Unuseful status. + * - 21 Unknow status. + */ + /*=============================================================================*/ + +static mp_obj_t qpy_sim_get_card_status(size_t n_args, const mp_obj_t *args) +{ + Helios_SIM_Status_e status = 0; + int ret = 0; + int cur_simid = 0 ; + if ( n_args > 0 ) + { + cur_simid = (uint8_t)mp_obj_get_int(args[0]); + }else{ + cur_simid = _get_current_simid(); + } + if ((cur_simid != 0) && (cur_simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); + } + MP_THREAD_GIL_EXIT(); + ret = Helios_SIM_GetCardStatus(cur_simid, &status); + MP_THREAD_GIL_ENTER(); + if (ret == 0) + { + return mp_obj_new_int(status); + } + return mp_obj_new_int(-1); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_sim_get_card_status_obj, 0, 1, qpy_sim_get_card_status); + +#if MICROPY_QPY_MODULE_PHB +static mp_obj_t qpy_sim_get_phonebookstatus(void) +{ + uint8_t pb_ready_flag = 0; + MP_THREAD_GIL_EXIT(); + Helios_SIM_GetPbReady(&pb_ready_flag); + MP_THREAD_GIL_ENTER(); + return mp_obj_new_int(pb_ready_flag); +} +static MP_DEFINE_CONST_FUN_OBJ_0(qpy_sim_get_phonebookstatus_obj, qpy_sim_get_phonebookstatus); +/*=============================================================================*/ +/* FUNCTION: qpy_sim_read_phonebook_record */ +/*=============================================================================*/ +/*!@brief : Read the phone book. + * + * @args[1] [in] the storage position of the phone book. + * @args[2] [in] start_index + * @args[3] [in] end_index + * @args[4] [in] username + * @return : + * -1 - error + * If it reads successfully, the results are returned in the following format. + * (record_number, [(index, username, phone_number), ... , (index, username, phone_number)]) + * For example: + * (2, [(1, 'zhangsan', '18122483511'), (2, 'lisi', '18122483542')]) + */ +/*=============================================================================*/ + +static mp_obj_t qpy_sim_read_phonebook_record(size_t n_args, const mp_obj_t *args) +{ + uint8_t i = 0; + int32_t storage = 0; + int cur_simid = 0; + Helios_SIMReadPhoneBookInfoStruct records = {0}; + mp_buffer_info_t nameinfo = {0}; + mp_obj_t list_records = mp_obj_new_list(0, NULL); + + if ( n_args > 4 ){ + cur_simid = mp_obj_get_int(args[4]); + }else{ + cur_simid = _get_current_simid(); + } + storage = mp_obj_get_int(args[0]); + records.start_index = mp_obj_get_int(args[1]); + records.end_index = mp_obj_get_int(args[2]); + mp_get_buffer_raise(args[3], &nameinfo, MP_BUFFER_READ); + + if ((storage < 0) || (storage > 15)) + { + mp_raise_ValueError(MP_ERROR_TEXT("invalid value, storage should be in (0,15).")); + } + if (records.end_index < records.start_index) + { + mp_raise_ValueError(MP_ERROR_TEXT("invalid value, end >= start.")); + } + if ((records.end_index - records.start_index) > 20) + { + mp_raise_ValueError(MP_ERROR_TEXT("invalid value, end - start <= 20.")); + } + if ((cur_simid != 0) && (cur_simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); + } + if (nameinfo.len > 30) + { + mp_raise_ValueError(MP_ERROR_TEXT("invalid value, the length of username should be no more than 30 bytes.")); + } + records.user_name = (char *)nameinfo.buf; + + MP_THREAD_GIL_EXIT(); + int ret = Helios_SIM_ReadPhonebookRecord(cur_simid, storage, &records); + MP_THREAD_GIL_ENTER(); + if (ret == 0) + { + for (i=0; i 4 ){ + cur_simid = mp_obj_get_int(args[4]); + } else{ + cur_simid = _get_current_simid(); + } + storage = mp_obj_get_int(args[0]); + record.index = mp_obj_get_int(args[1]); + mp_get_buffer_raise(args[2], &bufinfo[0], MP_BUFFER_READ); + mp_get_buffer_raise(args[3], &bufinfo[1], MP_BUFFER_READ); + + if ((storage < 0) || (storage > 15)) + { + mp_raise_ValueError(MP_ERROR_TEXT("invalid value, storage should be in (0,15).")); + } + if ((record.index < 1) || (record.index > 500)) + { + mp_raise_ValueError(MP_ERROR_TEXT("invalid value, index should be in (1,500).")); + } + if (bufinfo[0].len > 30) + { + mp_raise_ValueError(MP_ERROR_TEXT("invalid value, the length of username should be no more than 30 bytes.")); + } + if (bufinfo[1].len > 20) + { + mp_raise_ValueError(MP_ERROR_TEXT("invalid value, the length of phonenumber should be no more than 20 bytes.")); + } + if ((cur_simid != 0) && (cur_simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); + } + strncpy(record.user_name, bufinfo[0].buf, bufinfo[0].len); + strncpy(record.phone_num, bufinfo[1].buf, bufinfo[1].len); + + + MP_THREAD_GIL_EXIT(); + int ret = Helios_SIM_WritePhonebookRecord(cur_simid, storage, &record); + MP_THREAD_GIL_ENTER(); + if (ret == 0) + { + return mp_obj_new_int(0); + } + return mp_obj_new_int(-1); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_sim_write_phonebook_record_obj, 3,5, qpy_sim_write_phonebook_record); + +#endif + + +#if MICROPY_QPY_MODULE_SIMDET +static mp_obj_t qpy_sim_set_simdet(size_t n_args, const mp_obj_t *args) +{ + int ret = 0; + int cur_simid = 0; + + int detenable = 0; + int insertlevel = 0; + if ( n_args > 2 ){ + cur_simid = mp_obj_get_int(args[2]); + }else{ + cur_simid = _get_current_simid(); + } + detenable = mp_obj_get_int(args[0]); + insertlevel = mp_obj_get_int(args[1]); + + if (detenable != 0 && detenable != 1) + { + mp_raise_ValueError(MP_ERROR_TEXT("invalid value, detenable should be in (0,1).")); + } + if (insertlevel != 0 && insertlevel != 1) + { + mp_raise_ValueError(MP_ERROR_TEXT("invalid value, insertlevel should be in (0,1).")); + } + if ((cur_simid != 0) && (cur_simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); + } + MP_THREAD_GIL_EXIT(); + ret = Helios_SIM_SetSimDet(cur_simid, detenable, insertlevel); + MP_THREAD_GIL_ENTER(); + if (ret == 0) + { + return mp_obj_new_int(ret); + } + + return mp_obj_new_int(-1); +} + +static mp_obj_t qpy_sim_get_simdet(size_t n_args, const mp_obj_t *args) +{ + int ret = 0; + int detenable = 99; + int insertlevel = 99; + int cur_simid = 0; + if ( n_args > 0 ){ + cur_simid = mp_obj_get_int(args[0]); + }else{ + cur_simid = _get_current_simid(); + } + if ((cur_simid != 0) && (cur_simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); + } + MP_THREAD_GIL_EXIT(); + ret = Helios_SIM_GetSimDet(cur_simid, &detenable, &insertlevel); + MP_THREAD_GIL_ENTER(); + if (ret == 0) + { + mp_obj_t tuple[2] = + { + mp_obj_new_int(detenable), + mp_obj_new_int(insertlevel), + }; + return mp_obj_new_tuple(2, tuple); + } + + return mp_obj_new_int(-1); +} + +static c_callback_t *g_sim_user_callback; + +static void qpy_sim_event_handler(uint8_t sim_id, unsigned int event_id, void *ctx) +{ + if(g_sim_user_callback) + { + QPY_MODSIM_LOG("[SIM] callback start.\r\n"); + GC_STACKTOP_SET(); + mp_sched_schedule_ex(g_sim_user_callback, mp_obj_new_int(event_id)); + GC_STACKTOP_CLEAR(); + QPY_MODSIM_LOG("[SIM] callback end.\r\n"); + } +} + +static mp_obj_t qpy_sim_add_event_handler(mp_obj_t handler) +{ + static c_callback_t cb = {0}; + memset(&cb, 0, sizeof(c_callback_t)); + g_sim_user_callback = &cb; + mp_sched_schedule_callback_register(g_sim_user_callback, handler); + MP_THREAD_GIL_EXIT(); + Helios_SIM_Add_Event_Handler(qpy_sim_event_handler); + MP_THREAD_GIL_ENTER(); + return mp_obj_new_int(0); +} + +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_sim_set_simdet_obj, 2, 3, qpy_sim_set_simdet); + +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_sim_get_simdet_obj, 0, 1, qpy_sim_get_simdet); + +static MP_DEFINE_CONST_FUN_OBJ_1(qpy_sim_add_event_handler_obj, qpy_sim_add_event_handler); +#endif + +#if defined(PLAT_ASR) +static mp_obj_t qpy_sim_genericaccess(const mp_obj_t sim_id, const mp_obj_t cmd) +{ + Helios_SIMGenericAccesStruct info = {0}; + int simid = mp_obj_get_int(sim_id); + mp_buffer_info_t bufinfo = {0}; + mp_get_buffer_raise(cmd, &bufinfo, MP_BUFFER_READ); + + if (bufinfo.len <= 0) + { + mp_raise_ValueError(MP_ERROR_TEXT("invalid value, the length of cmd should be more than 0 bytes.")); + } + + if (simid != 0) + { + mp_raise_ValueError(MP_ERROR_TEXT("invalid simid.")); + } + + strncpy((char *)info.cmd, (const char *)bufinfo.buf, bufinfo.len); + info.len = bufinfo.len; + MP_THREAD_GIL_EXIT(); + int ret = Helios_SIM_GenericAccess(simid, &info); + MP_THREAD_GIL_ENTER(); + if (ret == 0) + { + mp_obj_t tuple[2] = + { + mp_obj_new_int(strlen(info.resp)), + mp_obj_new_str(info.resp, strlen(info.resp)), + }; + return mp_obj_new_tuple(2, tuple); + //return mp_obj_new_str(info.resp, strlen(info.resp)); + } + return mp_obj_new_int(-1); +} +static MP_DEFINE_CONST_FUN_OBJ_2(qpy_sim_genericaccess_obj, qpy_sim_genericaccess); +#endif + +#if MICROPY_QPY_MODULE_DUALSIM || MICROPY_QPY_MODULE_DSDS +static c_callback_t * g_switchsim_done_callback; + +static void switch_sim_done_callback(uint8_t state) +{ + if (g_switchsim_done_callback) + { + GC_STACKTOP_SET(); + mp_sched_schedule_ex(g_switchsim_done_callback, mp_obj_new_int(state)); + GC_STACKTOP_CLEAR(); + } +} + +static mp_obj_t qpy_sim_set_switchcard_cb(mp_obj_t switchsim_callback) +{ + static c_callback_t cb = {0}; + memset(&cb, 0, sizeof(c_callback_t)); + g_switchsim_done_callback = &cb; + mp_sched_schedule_callback_register(g_switchsim_done_callback, switchsim_callback); + + return mp_obj_new_int(0); +} +static MP_DEFINE_CONST_FUN_OBJ_1(qpy_sim_set_switchcard_cb_obj, qpy_sim_set_switchcard_cb); + +static mp_obj_t qpy_sim_switch_card(mp_obj_t sim_id) +{ + uint8_t simid = mp_obj_get_int(sim_id); + if ((simid != 0) && (simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simid should be in [0,1].")); + } +#if MICROPY_QPY_MODULE_DUALSIM + uint8_t old_simid = HELIOS_SIM_0; + MP_THREAD_GIL_EXIT(); + Helios_SIM_GetCurrentSimid(&old_simid); + MP_THREAD_GIL_ENTER(); + if (simid == old_simid) + { + return mp_obj_new_int(-1); + } +#endif + MP_THREAD_GIL_EXIT(); + int ret = Helios_SIM_SwitchCard(simid, switch_sim_done_callback); + MP_THREAD_GIL_ENTER(); + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_1(qpy_sim_switch_card_obj, qpy_sim_switch_card); + +static mp_obj_t qpy_sim_get_current_simid() +{ + uint8_t simid = HELIOS_SIM_0; + MP_THREAD_GIL_EXIT(); + Helios_SIM_GetCurrentSimid(&simid); + MP_THREAD_GIL_ENTER(); + return mp_obj_new_int(simid); +} +static MP_DEFINE_CONST_FUN_OBJ_0(qpy_sim_get_current_simid_obj, qpy_sim_get_current_simid); + +#if defined(BOARD_EC800MCN_LE_VOLVGL) || defined(BOARD_EC800MCN_LE_CPE) || defined(BOARD_EG810MEU_LA_VOLVGL) +static mp_obj_t qpy_sim_is_insert(mp_obj_t sim_id) +{ + int simid = mp_obj_get_int(sim_id); + if ((simid != 0) && (simid != 1)) + { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simid should be in [0,1].")); + } + uint8_t insert_sta = 0; + MP_THREAD_GIL_EXIT(); + Helios_SIM_GetInsertStatus(simid, &insert_sta); + MP_THREAD_GIL_ENTER(); + return mp_obj_new_bool(insert_sta); +} +static MP_DEFINE_CONST_FUN_OBJ_1(qpy_sim_is_insert_obj, qpy_sim_is_insert); +#endif + +#endif + +static mp_obj_t qpy_module_sim_deinit(void) +{ + #if MICROPY_QPY_MODULE_DUALSIM || MICROPY_QPY_MODULE_DSDS + g_switchsim_done_callback = NULL; + #endif + + #if MICROPY_QPY_MODULE_SIMDET + g_sim_user_callback = NULL; + MP_THREAD_GIL_EXIT(); + Helios_SIM_Add_Event_Handler(NULL); + MP_THREAD_GIL_ENTER(); + #endif + + return mp_obj_new_int(0); +} + +static MP_DEFINE_CONST_FUN_OBJ_0(qpy_module_sim_deinit_obj, qpy_module_sim_deinit); + +#if MICROPY_QPY_MODULE_ESIM_SIM_SWITCH +static mp_obj_t qpy_sim_get_esim_list(void) +{ + int ret = 0; + u08 profile_num =0; + profile_info_t card_info[THE_MAX_CARD_NUM] = {0}; + mp_obj_t list_profile = mp_obj_new_list(0, NULL); + MP_THREAD_GIL_EXIT(); + ret = rt_lpa_get_profile_info(card_info, &profile_num, THE_MAX_CARD_NUM); + MP_THREAD_GIL_ENTER(); + if (ret == 0) + { + int i = 0; + for (i = 0; i < profile_num; i++) + { + mp_obj_t profile_info[3] = { + mp_obj_new_str(card_info[i].iccid, strlen(card_info[i].iccid)), + mp_obj_new_int(card_info[i].state), + mp_obj_new_int(card_info[i].class)}; + mp_obj_list_append(list_profile, mp_obj_new_tuple(3, profile_info)); + } + } + mp_obj_t tuple[2] = + { + mp_obj_new_int(profile_num), + list_profile, + }; + return mp_obj_new_tuple(2, tuple); +} +static MP_DEFINE_CONST_FUN_OBJ_0(qpy_sim_get_esim_list_obj, qpy_sim_get_esim_list); + + +static mp_obj_t qpy_sim_get_esim_eid(void) +{ + char eid_buf[MAX_EID_HEX_LEN] = {0}; + char eid[MAX_EID_LEN] = {0}; + int ret = -1; + MP_THREAD_GIL_EXIT(); + ret = rt_lpa_get_eid((u08 *)eid_buf); + rt_utils_bytes_to_hex((cpu08)eid_buf, sizeof(eid_buf), eid); + MP_THREAD_GIL_ENTER(); + if (ret != 0) + { + memset(eid, 0, sizeof(eid)); + } + return mp_obj_new_str(eid, strlen(eid)); +} +static MP_DEFINE_CONST_FUN_OBJ_0(qpy_sim_get_esim_eid_obj, qpy_sim_get_esim_eid); + +static mp_obj_t qpy_sim_enable_esim(const mp_obj_t iccid) +{ + int ret = -1; + mp_buffer_info_t qpy_iccid = {0}; + mp_get_buffer_raise(iccid, &qpy_iccid, MP_BUFFER_READ); + + if (qpy_iccid.len != 20) + { + mp_raise_ValueError(MP_ERROR_TEXT("invalid value, the length of iccid should be 20 bytes.")); + } + MP_THREAD_GIL_EXIT(); + ret = rt_lpa_enable_profile(qpy_iccid.buf); + MP_THREAD_GIL_ENTER(); + return mp_obj_new_int(ret); +} +static MP_DEFINE_CONST_FUN_OBJ_1(qpy_sim_enable_esim_obj, qpy_sim_enable_esim); +#endif + +#if MICROPY_QPY_MODULE_ESIM +extern const struct _mp_obj_module_t mp_module_esim; +#endif + +static const mp_rom_map_elem_t mp_module_sim_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_sim) }, + +#if MICROPY_QPY_MODULE_ESIM + { MP_ROM_QSTR(MP_QSTR_esim), MP_ROM_PTR(&mp_module_esim) }, +#endif + + { MP_ROM_QSTR(MP_QSTR_getImsi), MP_ROM_PTR(&qpy_sim_get_imsi_obj) }, + { MP_ROM_QSTR(MP_QSTR_getIccid), MP_ROM_PTR(&qpy_sim_get_iccid_obj) }, + +#ifndef MICROPY_QPY_MODULE_NO_SIMPIN + { MP_ROM_QSTR(MP_QSTR_verifyPin), MP_ROM_PTR(&qpy_sim_verify_pin_obj) }, + { MP_ROM_QSTR(MP_QSTR_changePin), MP_ROM_PTR(&qpy_sim_change_pin_obj) }, + { MP_ROM_QSTR(MP_QSTR_unblockPin), MP_ROM_PTR(&qpy_sim_unblock_pin_obj) }, + + { MP_ROM_QSTR(MP_QSTR_enablePin), MP_ROM_PTR(&qpy_sim_enable_pin_obj) }, + { MP_ROM_QSTR(MP_QSTR_disablePin), MP_ROM_PTR(&qpy_sim_disable_pin_obj) }, +#endif + + { MP_ROM_QSTR(MP_QSTR_getStatus), MP_ROM_PTR(&qpy_sim_get_card_status_obj)}, +#if MICROPY_QPY_MODULE_PHB + { MP_ROM_QSTR(MP_QSTR_getPhonebookStatus), MP_ROM_PTR(&qpy_sim_get_phonebookstatus_obj) }, + { MP_ROM_QSTR(MP_QSTR_readPhonebook), MP_ROM_PTR(&qpy_sim_read_phonebook_record_obj) }, + { MP_ROM_QSTR(MP_QSTR_writePhonebook), MP_ROM_PTR(&qpy_sim_write_phonebook_record_obj) }, +#endif +#if defined (PLAT_ASR) + { MP_ROM_QSTR(MP_QSTR_genericAccess), MP_ROM_PTR(&qpy_sim_genericaccess_obj) }, +#endif +#if MICROPY_QPY_MODULE_DUALSIM || MICROPY_QPY_MODULE_DSDS + { MP_ROM_QSTR(MP_QSTR_switchCard), MP_ROM_PTR(&qpy_sim_switch_card_obj) }, + { MP_ROM_QSTR(MP_QSTR_setSwitchcardCallback), MP_ROM_PTR(&qpy_sim_set_switchcard_cb_obj) }, + { MP_ROM_QSTR(MP_QSTR_getCurSimid), MP_ROM_PTR(&qpy_sim_get_current_simid_obj) }, +#if defined(BOARD_EC800MCN_LE_VOLVGL) || defined(BOARD_EC800MCN_LE_CPE) || defined(BOARD_EG810MEU_LA_VOLVGL) + { MP_ROM_QSTR(MP_QSTR_isInsert), MP_ROM_PTR(&qpy_sim_is_insert_obj) }, +#endif +#endif +#if MICROPY_QPY_MODULE_SIMDET + { MP_ROM_QSTR(MP_QSTR_setSimDet), MP_ROM_PTR(&qpy_sim_set_simdet_obj) }, + { MP_ROM_QSTR(MP_QSTR_getSimDet), MP_ROM_PTR(&qpy_sim_get_simdet_obj) }, + { MP_ROM_QSTR(MP_QSTR_setCallback), MP_ROM_PTR(&qpy_sim_add_event_handler_obj) }, +#endif + + { MP_ROM_QSTR(MP_QSTR___qpy_module_deinit__), MP_ROM_PTR(&qpy_module_sim_deinit_obj) }, + +#if !defined (PLAT_RDA) + { MP_ROM_QSTR(MP_QSTR_getPhoneNumber), MP_ROM_PTR(&qpy_sim_get_phonenumber_obj)}, +#endif +#if MICROPY_QPY_MODULE_PIN_REMATTEMPTS + { MP_ROM_QSTR(MP_QSTR_getPinRemAttempts), MP_ROM_PTR(&qpy_sim_pin_remain_attempts_obj) }, +#endif +#if MICROPY_QPY_MODULE_ESIM_SIM_SWITCH + { MP_ROM_QSTR(MP_QSTR_eSimGetList), MP_ROM_PTR(&qpy_sim_get_esim_list_obj) }, + { MP_ROM_QSTR(MP_QSTR_eSimGetEid), MP_ROM_PTR(&qpy_sim_get_esim_eid_obj) }, + { MP_ROM_QSTR(MP_QSTR_eSimSwitch), MP_ROM_PTR(&qpy_sim_enable_esim_obj) }, +#endif +}; +static MP_DEFINE_CONST_DICT(mp_module_sim_globals, mp_module_sim_globals_table); + + +const mp_obj_module_t mp_module_sim = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&mp_module_sim_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_sim, mp_module_sim); +#endif + + diff --git a/ports/quectel/modsim.h b/ports/quectel/modsim.h new file mode 100644 index 0000000000000..ecd199080932e --- /dev/null +++ b/ports/quectel/modsim.h @@ -0,0 +1,222 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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 __MODSIM_H__ +#define __MODSIM_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define QL_SIM_MCC_LEN 4 /** Length of the MCC. */ +#define QL_SIM_MNC_MAX 4 /** Maximum length of the MNC. */ +#define QL_SIM_PLMN_NUM_MAX 24 /** Maximum number of PLMN data sets. */ + +typedef enum +{ + QL_SIM_SUCCESS, + QL_SIM_GENERIC_FAILURE, +}QL_SIM_ERROR_CODE; + + + +typedef struct +{ + uint8_t mcc[QL_SIM_MCC_LEN]; /**< MCC value in ASCII characters.*/ + uint8_t mnc[QL_SIM_MNC_MAX]; /**< MNC value in ASCII characters.*/ +}QL_SIM_PLMN_INFO; + +typedef struct +{ + unsigned int preferred_operator_list_num; /**< Must be set to the number of elements in preferred_operator_list. */ + QL_SIM_PLMN_INFO preferred_operator_list[QL_SIM_PLMN_NUM_MAX]; /**< Preferred operator list. */ +}QL_SIM_PREFERRED_OPERATOR_LIST; /* Message */ + +#define QL_SIM_PIN_LEN_MAX 16 /** Maximum length of PIN data. */ +typedef struct +{ + uint8_t pin_value[QL_SIM_PIN_LEN_MAX]; /* Value of the PIN */ +}QL_SIM_VERIFY_PIN_INFO; + +typedef struct +{ + uint8_t old_pin_value[QL_SIM_PIN_LEN_MAX]; /**< Value of the old PIN as a sequence of ASCII characters. */ + uint8_t new_pin_value[QL_SIM_PIN_LEN_MAX]; /**< Value of the new PIN as a sequence of ASCII characters. */ +}QL_SIM_CHANGE_PIN_INFO; + +typedef struct +{ + uint8_t puk_value[QL_SIM_PIN_LEN_MAX]; /**< Value of the PUK as a sequence of ASCII characters. */ + uint8_t new_pin_value[QL_SIM_PIN_LEN_MAX]; /**< Value of the new PIN as a sequence of ASCII characters. */ +}QL_SIM_UNBLOCK_PIN_INFO; + +typedef enum +{ + QL_SIM_CARD_TYPE_UNKNOWN = 0, /**< Unidentified card type. */ + QL_SIM_CARD_TYPE_ICC = 1, /**< Card of SIM or RUIM type. */ + QL_SIM_CARD_TYPE_UICC = 2, /**< Card of USIM or CSIM type. */ +}QL_SIM_CARD_TYPE; + +typedef enum +{ + QL_SIM_STATUS_NOT_INSERTED, + QL_SIM_STATUS_READY, + QL_SIM_STATUS_SIM_PIN, + QL_SIM_STATUS_SIM_PUK, + QL_SIM_STATUS_PH_SIM_LOCK_PIN, + QL_SIM_STATUS_PH_SIM_LOCK_PUK, + QL_SIM_STATUS_PH_FSIM_PIN, + QL_SIM_STATUS_PH_FSIM_PUK, + QL_SIM_STATUS_SIM_PIN2, + QL_SIM_STATUS_SIM_PUK2, + QL_SIM_STATUS_PH_NET_PIN, + QL_SIM_STATUS_PH_NET_PUK, + QL_SIM_STATUS_PH_NET_SUB_PIN, + QL_SIM_STATUS_PH_NET_SUB_PUK, + QL_SIM_STATUS_PH_SP_PIN, + QL_SIM_STATUS_PH_SP_PUK, + QL_SIM_STATUS_PH_CORP_PIN, + QL_SIM_STATUS_PH_CORP_PUK, + QL_SIM_STATUS_BUSY, + QL_SIM_STATUS_BLOCKED, + QL_SIM_STATUS_UNKNOWN +}QL_SIM_STATUS; /**< Card state. */ + +typedef struct +{ + uint8_t pin1_num_retries; /**< Number of PIN 1 retries. */ + uint8_t puk1_num_retries; /**< Number of PUK 1 retries. */ + uint8_t pin2_num_retries; /**< Number of PIN 2 retries. */ + uint8_t puk2_num_retries; /**< Number of PUK 2 retries. */ +}QL_SIM_CARD_PIN_INFO; + + + +typedef struct +{ + QL_SIM_CARD_TYPE card_type; // SIM card type + QL_SIM_STATUS card_state; //SIM card state + QL_SIM_CARD_PIN_INFO card_pin_info; // PIN info +}QL_SIM_CARD_INFO; + +typedef enum +{ + QL_SIM_FILE_TYPE_UNKNOWN = 0, /**< Unknown file type */ + QL_SIM_FILE_TYPE_TRANSPARENT = 1, /**< File structure consisting of a sequence of bytes. */ + QL_SIM_FILE_TYPE_CYCLIC = 2, /**< File structure consisting of a sequence of records, each containing the same fixed size in + chronological order. Once all the records have been used, the oldest data is overwritten. */ + QL_SIM_FILE_TYPE_LINEAR_FIXED = 3, /**< File structure consisting of a sequence of records, each containing the same fixed size. */ +}QL_SIM_FILE_TYPE; + +typedef enum +{ + QL_SIM_FILE_ACCESS_TYPE_ALWAYS =0, + QL_SIM_FILE_ACCESS_TYPE_CHV1 =1, + QL_SIM_FILE_ACCESS_TYPE_CHV2 =2, + QL_SIM_FILE_ACCESS_TYPE_ADM =3, +}QL_SIM_FILE_ACCESS_TYPE; + +typedef struct +{ + QL_SIM_FILE_ACCESS_TYPE read_access; + QL_SIM_FILE_ACCESS_TYPE update_access; +}QL_SIM_FILE_ACCESS_INFO; + +typedef enum +{ + QL_SIM_FILE_STATUS_INVALID =0, + QL_SIM_FILE_STATUS_EFFECTIVE =1, +}QL_SIM_FILE_STATUS; + + +typedef struct +{ + unsigned int id; + QL_SIM_FILE_TYPE type; /**< File type: */ + QL_SIM_FILE_ACCESS_INFO access; /**< File access conditions: */ + QL_SIM_FILE_STATUS status; /**< File status: */ + unsigned int size; /**< Size of transparent files.*/ + unsigned int record_len; /**< Size of each cyclic or linear fixed file record.*/ + unsigned int record_count; /**< Number of cyclic or linear fixed file records.*/ +}QL_SIM_FILE_INFO; + +typedef struct +{ + int sw1; + int sw2; +}QL_SIM_FILE_OPERATION_RET; + +#define QL_SIM_DATA_LEN_MAX 255 +typedef struct +{ + unsigned int data_len; /**< Must be set to the number of elements in data. */ + uint8_t data[QL_SIM_DATA_LEN_MAX]; /**< Data retrieved from the card. */ +}QL_SIM_CARD_FILE_DATA; + +typedef enum +{ + QL_SIM_PHONE_BOOK_STORAGE_DC, /**< 0 - ME dialed calls list */ + QL_SIM_PHONE_BOOK_STORAGE_EN, /**< 1 - SIM (or ME) emergency number */ + QL_SIM_PHONE_BOOK_STORAGE_FD, /**< 2 - SIM fix dialing-phone book */ + QL_SIM_PHONE_BOOK_STORAGE_LD, /**< 3 - SIM last-dialing-phone book */ + QL_SIM_PHONE_BOOK_STORAGE_MC, /**< 4 - ME missed (unanswered) calls list */ + QL_SIM_PHONE_BOOK_STORAGE_ME, /**< 5 - Mobile equipment phonebook */ + QL_SIM_PHONE_BOOK_STORAGE_MT, /**< 6 - */ + QL_SIM_PHONE_BOOK_STORAGE_ON, /**< 7 - SIM own numbers (MSISDNs) list */ + QL_SIM_PHONE_BOOK_STORAGE_RC, /**< 8 - ME received calls list */ + QL_SIM_PHONE_BOOK_STORAGE_SM, /**< 9 - SIM phonebook */ + QL_SIM_PHONE_BOOK_STORAGE_AP, /**< 10 - */ + QL_SIM_PHONE_BOOK_STORAGE_MBDN, /**< 11 - */ + QL_SIM_PHONE_BOOK_STORAGE_MN, /**< 12 - */ + QL_SIM_PHONE_BOOK_STORAGE_SDN, /**< 13 - */ + QL_SIM_PHONE_BOOK_STORAGE_ICI, /**< 14 - */ + QL_SIM_PHONE_BOOK_STORAGE_OCI, /**< 15 - */ +}QL_SIM_PHONE_BOOK_STORAGE; + +#define QL_SIM_PHONE_BOOK_RECORDS_MAX_COUNT 20 + +typedef struct +{ // when write, if phonenum is empty, it means to delete this item specified by index + int index; // the record index in phone book + uint8_t username[32]; // username + uint8_t phonenum[24]; // Phone number, it can include '+'*/ +}QL_SIM_PHONE_BOOK_RECORD_INFO; + + +typedef struct +{ + int record_count; //the count of record + QL_SIM_PHONE_BOOK_RECORD_INFO record[QL_SIM_PHONE_BOOK_RECORDS_MAX_COUNT]; // the list of record +}QL_SIM_PHONE_BOOK_RECORDS_INFO; + + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/ports/quectel/modsocket.c b/ports/quectel/modsocket.c new file mode 100644 index 0000000000000..96921d480425e --- /dev/null +++ b/ports/quectel/modsocket.c @@ -0,0 +1,1280 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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 +#include "mpconfigport.h" + +#if MICROPY_QPY_MODULE_USOCKET +#include "mpconfigboard.h" + +#include "py/runtime0.h" +#include "py/nlr.h" +#include "py/objlist.h" +#include "py/objstr.h" +#include "py/runtime.h" +#include "py/mperrno.h" +#include "py/mphal.h" +#include "py/stream.h" +#include "py/mperrno.h" +#include "shared/netutils/netutils.h" + +#if defined(PLAT_SONY_ALT1350) +#include "sockets.h" +#include "netdb.h" +#include "ip4.h" +#include "igmp.h" +#include "ip_addr.h" +#include "errno.h" + +#else +#include "lwip/sockets.h" +#include "lwip/netdb.h" +#include "lwip/ip4.h" +#include "lwip/igmp.h" +#endif + +#include "helios_datacall.h" + +#define SOCKET_POLL_US (100000) +#define MDNS_QUERY_TIMEOUT_MS (5000) +#define MDNS_LOCAL_SUFFIX ".local" +#define TIMEOUT_MAX (0xFFFFFFFF) + + +enum { + SOCKET_STATE_NEW, + SOCKET_STATE_CONNECTED, + SOCKET_STATE_PEER_CLOSED, +}; + +typedef struct _socket_obj_t { + mp_obj_base_t base; + int fd; + int timeout; + uint8_t domain; + uint8_t type; + uint8_t proto; + uint8_t state; + unsigned int retries; + #if MICROPY_PY_USOCKET_EVENTS + mp_obj_t events_callback; + struct _socket_obj_t *events_next; + #endif +} socket_obj_t; + +void _socket_settimeout(socket_obj_t *sock, uint64_t timeout_ms); + +#if MICROPY_PY_USOCKET_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; + +void usocket_events_deinit(void) { + usocket_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; +} + +// 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) { + if (*s == sock) { + *s = (*s)->events_next; + return; + } + } +} + +// Polls all registered sockets for readability and calls their callback if they are readable +void usocket_events_handler(void) { + if (usocket_events_head == NULL) { + return; + } + if (--usocket_events_divisor) { + return; + } + usocket_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) { + FD_SET(s->fd, &rfds); + max_fd = MAX(max_fd, s->fd); + } + + // Poll the sockets + struct timeval timeout = { .tv_sec = 0, .tv_usec = 0 }; + int r = select(max_fd + 1, &rfds, NULL, NULL, &timeout); + if (r <= 0) { + return; + } + + // Call the callbacks + for (socket_obj_t *s = usocket_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 + +static inline void check_for_exceptions(void) { + mp_handle_pending(true); +} + +// This function mimics lwip_getaddrinfo, with added support for mDNS queries +static int _socket_getaddrinfo3(const char *nodename, const char *servname, + const struct addrinfo *hints, struct addrinfo **res) { + +#if defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) + int pdp = 1;//Helios_DataCall_GetCurrentPDP(); + return getaddrinfowithcid(nodename, servname, hints, res, pdp); + +#elif defined(PLAT_SONY_ALT1350) + return lwip_getaddrinfo(nodename, servname, hints, res, NULL); +#else + int pdp = Helios_DataCall_GetCurrentPDP(); + + // Normal query + return getaddrinfo_with_pcid(nodename, servname, hints, res, pdp); +#endif +} +extern void mp_hal_stdout_tx_str(const char *str); +static int _socket_getaddrinfo2(const mp_obj_t host, const mp_obj_t portx, struct addrinfo **resp) { +#if defined(PLAT_SONY_ALT1350) + const struct addrinfo hints = { + .ai_family = AF_INET, + .ai_socktype = SOCK_DGRAM, + .ai_protocol = IPPROTO_UDP, + }; +#else + const struct addrinfo hints = { + .ai_family = AF_UNSPEC,//AF_INET, + .ai_socktype = SOCK_STREAM, + }; +#endif + + mp_obj_t port = portx; + if (mp_obj_is_small_int(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); + } + const char *host_str = mp_obj_str_get_str(host); + const char *port_str = mp_obj_str_get_str(port); + + if (host_str[0] == '\0') { + // a host of "" is equivalent to the default/all-local IP address + host_str = "0.0.0.0"; + } + + MP_THREAD_GIL_EXIT(); + int res = _socket_getaddrinfo3(host_str, port_str, &hints, resp); + MP_THREAD_GIL_ENTER(); + + // Per docs: instead of raising gaierror getaddrinfo raises negative error number + if (res != 0) { + mp_raise_OSError(res > 0 ? -res : res); + } + // Somehow LwIP returns a resolution of 0.0.0.0 for failed lookups, traced it as far back + // as netconn_gethostbyname_addrtype returning OK instead of error. + if (*resp == NULL || + (strcmp(resp[0]->ai_canonname, "0.0.0.0") == 0 && strcmp(host_str, "0.0.0.0") != 0)) { + mp_raise_OSError(-2); // name or service not known + } + + return res; +} + +static void _socket_getaddrinfo(const mp_obj_t addrtuple, struct addrinfo **resp) { + mp_obj_t *elem; + mp_obj_get_array_fixed_n(addrtuple, 2, &elem); + _socket_getaddrinfo2(elem[0], elem[1], resp); +} + +static mp_obj_t socket_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, 0, 3, false); + + //socket_obj_t *sock = mp_obj_malloc_with_finaliser(socket_obj_t, usocket_events_head); + socket_obj_t *sock = (socket_obj_t *) m_malloc_with_finaliser(sizeof(socket_obj_t)); + sock->base.type = type_in; + sock->domain = AF_INET; + sock->type = SOCK_STREAM; + sock->proto = 0; + if (n_args > 0) { + sock->domain = mp_obj_get_int(args[0]); + if (n_args > 1) { + sock->type = mp_obj_get_int(args[1]); + if (n_args > 2) { + sock->proto = mp_obj_get_int(args[2]); + } + } + } + + sock->state = sock->type == SOCK_STREAM ? SOCKET_STATE_NEW : SOCKET_STATE_CONNECTED; + + sock->fd = lwip_socket(sock->domain, sock->type, sock->proto); + if (sock->fd < 0) { +#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) + int socket_errno = lwip_get_soc_errno(); +#elif defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) + int socket_errno = EINVAL; +#else + int socket_errno = errno; +#endif + mp_raise_OSError(socket_errno); + } + +#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) + if ((sock->proto != 7) && (sock->proto != 8)) + { + Helios_DataCallInfoStruct info = {0}; + int ret = 0, pid = 0; + for (pid=1; pid<5; pid++) + { + ret = Helios_DataCall_GetInfo(pid, 0, &info); + if (ret == 0) + { + if ((info.v4.state == 1) || (info.v6.state == 1)) + { + break; + } + } + } + + if (ret != 0) + { + mp_raise_OSError(-1); + } + + if (sock->domain == AF_INET) + { + struct sockaddr_in server_addr; + memset(&server_addr, 0, sizeof(server_addr)); + + char ip4_ip_addr[16] = {0}; + inet_ntop(AF_INET, &info.v4.addr.ip, ip4_ip_addr, sizeof(ip4_ip_addr)); + inet_pton(AF_INET, ip4_ip_addr, &server_addr.sin_addr.s_addr); + + server_addr.sin_family = AF_INET; + server_addr.sin_port = 0; + lwip_bind(sock->fd, (struct sockaddr*)&server_addr, sizeof(struct sockaddr_in)); + } + else if (sock->domain == AF_INET6) + { + struct sockaddr_in6 local_v6; + memset(&local_v6, 0, sizeof(local_v6)); + + char ip6_ip_addr[64] = {0}; + inet_ntop(AF_INET6, &info.v6.addr.ip, ip6_ip_addr, sizeof(ip6_ip_addr)); + inet_pton(AF_INET6, ip6_ip_addr, &local_v6.sin6_addr); + + local_v6.sin6_family = AF_INET6; + local_v6.sin6_port = 0; + lwip_bind(sock->fd, (struct sockaddr *)&local_v6, sizeof(struct sockaddr_in6)); + } + } +#endif + + _socket_settimeout(sock, TIMEOUT_MAX); + + return MP_OBJ_FROM_PTR(sock); +} + +static mp_obj_t socket_bind(const mp_obj_t arg0, const mp_obj_t arg1) { + socket_obj_t *self = MP_OBJ_TO_PTR(arg0); + + mp_obj_t *elem; + mp_obj_get_array_fixed_n(arg1, 2, &elem); + const char *addr_info = mp_obj_str_get_str(elem[0]); + int server_port = mp_obj_get_int(elem[1]); + + Helios_DataCallInfoStruct info = {0}; + if (addr_info[0] == '\0') + { + int ret = 0, pid = 0; + for (pid=1; pid<5; pid++) + { + ret = Helios_DataCall_GetInfo(pid, 0, &info); + if (ret == 0) + { + if ((info.v4.state == 1) || (info.v6.state == 1)) + { + break; + } + } + } + + if (ret != 0) + { + mp_raise_OSError(-1); + } + } + + if (self->domain == AF_INET) + { + struct sockaddr_in server_addr; + memset(&server_addr, 0, sizeof(server_addr)); + server_addr.sin_family = AF_INET; +#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) + server_addr.sin_port = lwip_htons(server_port); +#elif defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) || defined(PLAT_SONY_ALT1350) + server_addr.sin_port = htons(server_port); +#endif + + if (addr_info[0] == '\0') + { + char ip4_ip_addr[16] = {0}; + inet_ntop(AF_INET, &info.v4.addr.ip, ip4_ip_addr, sizeof(ip4_ip_addr)); + inet_pton(AF_INET, ip4_ip_addr, &server_addr.sin_addr.s_addr); + } + else + { + inet_pton(AF_INET, addr_info, &server_addr.sin_addr.s_addr); + } + + lwip_bind(self->fd, (struct sockaddr*)&server_addr, sizeof(struct sockaddr_in)); + } + else if (self->domain == AF_INET6) + { + struct sockaddr_in6 local_v6; + memset(&local_v6, 0, sizeof(local_v6)); + + local_v6.sin6_family = AF_INET6; +#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) + local_v6.sin6_port = lwip_htons(server_port); +#elif defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) || defined(PLAT_SONY_ALT1350) + local_v6.sin6_port = htons(server_port); +#endif + + if (addr_info[0] == '\0') + { + char ip6_ip_addr[64] = {0}; + inet_ntop(AF_INET6, &info.v6.addr.ip, ip6_ip_addr, sizeof(ip6_ip_addr)); + //QPY_SOCKET_LOG("[socket][%s][%d]bind IPV6 datacall info .\r\n", ip6_ip_addr, server_port); + inet_pton(AF_INET6, ip6_ip_addr, &local_v6.sin6_addr); + } + else + { + inet_pton(AF_INET6, addr_info, &local_v6.sin6_addr); + //QPY_SOCKET_LOG("[socket][%s][%d]bind IPV6 addr info .\r\n", addr_info, server_port); + } + + lwip_bind(self->fd, (struct sockaddr *)&local_v6, sizeof(struct sockaddr_in6)); + } + + 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) { + socket_obj_t *self = MP_OBJ_TO_PTR(args[0]); + + int backlog = 0; + if (n_args > 1) { + backlog = mp_obj_get_int(args[1]); + backlog = (backlog < 0) ? 0 : backlog; + } + + self->state = SOCKET_STATE_CONNECTED; + int r = lwip_listen(self->fd, backlog); + if (r < 0) { +#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) + int socket_errno = lwip_get_soc_errno(); +#else + int socket_errno = errno; +#endif + mp_raise_OSError(socket_errno); + } + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_listen_obj, 1, 2, socket_listen); + +static mp_obj_t socket_accept(const mp_obj_t arg0) { + socket_obj_t *self = MP_OBJ_TO_PTR(arg0); + mp_obj_t tuple[3]; + char ip4_addr_buf[16] = {0}; + char ip6_addr_buf[128] = {0}; + int ip4_port = 0; + int ip6_port = 0; + + int new_fd = -1; + for (unsigned int i = 0; i <= self->retries; i++) + { + if (self->domain == AF_INET) + { +#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) || defined(PLAT_SONY_ALT1350) + struct sockaddr_in addr_v4; + socklen_t addr_v4_len = sizeof(struct sockaddr_in); + + MP_THREAD_GIL_EXIT(); + new_fd = lwip_accept(self->fd, (struct sockaddr *)&addr_v4, &addr_v4_len); + MP_THREAD_GIL_ENTER(); + +#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) + int socket_errno = lwip_get_soc_errno(); +#else + int socket_errno = errno; +#endif + if (socket_errno != EAGAIN) { + mp_raise_OSError(socket_errno); + } + + inet_ntop(AF_INET, &addr_v4.sin_addr, ip4_addr_buf, sizeof(ip4_addr_buf)); + ip4_port = ntohs(addr_v4.sin_port); +#endif + } + else if (self->domain == AF_INET6) + { +#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) || defined(PLAT_SONY_ALT1350) + struct sockaddr_in6 addr_v6; + socklen_t addr_v6_len = sizeof(struct sockaddr_in6); + + MP_THREAD_GIL_EXIT(); + new_fd = lwip_accept(self->fd, (struct sockaddr *)&addr_v6, &addr_v6_len); + MP_THREAD_GIL_ENTER(); + +#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) + int socket_errno = lwip_get_soc_errno(); +#else + int socket_errno = errno; +#endif + if (socket_errno != EAGAIN) { + mp_raise_OSError(socket_errno); + } + + inet_ntop(AF_INET6, &addr_v6.sin6_addr, ip6_addr_buf, sizeof(ip6_addr_buf)); + ip6_port = ntohs(addr_v6.sin6_port); +#endif + } + + if (new_fd >= 0) { + break; + } + + check_for_exceptions(); + } + + if (new_fd < 0) + { + if (self->retries == 0) { + mp_raise_OSError(MP_EAGAIN); + } else { + mp_raise_OSError(MP_ETIMEDOUT); + } + } + + // create new socket object + socket_obj_t *sock = (socket_obj_t *) m_malloc_with_finaliser(sizeof(socket_obj_t)); + sock->base.type = self->base.type; + sock->fd = new_fd; + sock->domain = self->domain; + sock->type = self->type; + sock->proto = self->proto; + sock->state = SOCKET_STATE_CONNECTED; + tuple[0] = MP_OBJ_FROM_PTR(sock); + + if (self->domain == AF_INET) + { + tuple[1] = mp_obj_new_str(ip4_addr_buf, strlen(ip4_addr_buf)); + tuple[2] = mp_obj_new_int(ip4_port); + } + else if (self->domain == AF_INET6) + { + tuple[1] = mp_obj_new_str(ip6_addr_buf, strlen(ip6_addr_buf)); + tuple[2] = mp_obj_new_int(ip6_port); + } + + _socket_settimeout(sock, TIMEOUT_MAX); + return mp_obj_new_tuple(3, tuple); +} +static MP_DEFINE_CONST_FUN_OBJ_1(socket_accept_obj, socket_accept); + +static mp_obj_t socket_connect(const mp_obj_t arg0, const mp_obj_t arg1) { + socket_obj_t *self = MP_OBJ_TO_PTR(arg0); + int r = 0; + + if ((self->type == SOCK_STREAM) && (self->state == SOCKET_STATE_CONNECTED)){ + mp_raise_OSError(114); + } + + self->state = SOCKET_STATE_CONNECTED; + + struct addrinfo *res; + _socket_getaddrinfo(arg1, &res); + + if (self->timeout > 0 && self->timeout < 25) + { + int sock_nbio = 1; + lwip_ioctl(self->fd, FIONBIO, &sock_nbio); + + MP_THREAD_GIL_EXIT(); + r = lwip_connect(self->fd, res->ai_addr, res->ai_addrlen); + MP_THREAD_GIL_ENTER(); +#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) + int socket_errno = lwip_get_soc_errno(); +#else + int socket_errno = errno; +#endif + +#if defined(PLAT_SONY_ALT1350) + if((r == -1) && (socket_errno != 119)) +#else + if((r == -1) && (socket_errno != 115)) +#endif + { + lwip_freeaddrinfo(res); + mp_raise_OSError(socket_errno); + } + + lwip_freeaddrinfo(res); + + struct timeval t; + t.tv_sec = self->timeout; + t.tv_usec = 0; + +#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) + fd_set read_fds, write_fds; + FD_ZERO(&read_fds); + FD_SET(self->fd, &read_fds); + FD_ZERO(&write_fds); + FD_SET(self->fd, &write_fds); + + MP_THREAD_GIL_EXIT(); + r = lwip_select(self->fd + 1, &read_fds, &write_fds, NULL, &t); + MP_THREAD_GIL_ENTER(); + + if(r <= 0) + { + mp_raise_OSError(MP_ETIMEDOUT); + } + + int value; + int len = sizeof(value); + //get so_error to check connect be RST or not + getsockopt(self->fd, SOL_SOCKET, SO_ERROR, &value, (socklen_t *)&len); + if(value == ECONNRESET) + { + mp_raise_OSError(ECONNRESET); + } +#elif defined(PLAT_SONY_ALT1350) + fd_set read_fds, write_fds; + FD_ZERO(&read_fds);FD_ZERO(&write_fds); + FD_SET(self->fd, &read_fds);FD_SET(self->fd, &write_fds); + + MP_THREAD_GIL_EXIT(); + r = lwip_select(self->fd + 1, &read_fds, &write_fds, NULL, &t); + MP_THREAD_GIL_ENTER(); + + if(r <= 0) + { + mp_raise_OSError(MP_ETIMEDOUT); + } + else + { + if (FD_ISSET(self->fd, &read_fds)) + { + char buf[10]; + int bytes = lwip_recvfrom(self->fd, buf, 0, 0, NULL, NULL); + + socket_errno = errno; + if(bytes < 0) + { + mp_raise_OSError(socket_errno); + } + } + } +#else + fd_set read_fds; + FD_ZERO(&read_fds); + FD_SET(self->fd, &read_fds); + + MP_THREAD_GIL_EXIT(); + r = lwip_select(self->fd + 1, &read_fds, NULL, NULL, &t); + MP_THREAD_GIL_ENTER(); + + if(r <= 0) + { + mp_raise_OSError(MP_ETIMEDOUT); + } +#endif + + sock_nbio = 0; + lwip_ioctl(self->fd, FIONBIO, &sock_nbio); + } + else + { + MP_THREAD_GIL_EXIT(); + r = lwip_connect(self->fd, res->ai_addr, res->ai_addrlen); + MP_THREAD_GIL_ENTER(); +#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) + int socket_errno = lwip_get_soc_errno(); +#else + int socket_errno = errno; +#endif + if (r != 0) + { + lwip_freeaddrinfo(res); + mp_raise_OSError(socket_errno); + } + lwip_freeaddrinfo(res); + } + + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_2(socket_connect_obj, socket_connect); + +static mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) { + (void)n_args; // always 4 + socket_obj_t *self = MP_OBJ_TO_PTR(args[0]); + + int opt = mp_obj_get_int(args[2]); + + switch (opt) { + // level: SOL_SOCKET + case SO_REUSEADDR: { + int val = mp_obj_get_int(args[3]); + int ret = lwip_setsockopt(self->fd, SOL_SOCKET, opt, &val, sizeof(int)); + if (ret != 0) { +#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) + int socket_errno = lwip_get_soc_errno(); +#else + int socket_errno = errno; +#endif + mp_raise_OSError(socket_errno); + } + break; + } + + case TCP_KEEPALIVE: { + if (self->type == SOCK_STREAM) + { + int val = mp_obj_get_int(args[3]); + int optval = 1; + int ret = lwip_setsockopt(self->fd, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(int)); + + optval = val*60; + ret = lwip_setsockopt(self->fd, IPPROTO_TCP, TCP_KEEPIDLE, &optval, sizeof(int)); + + optval = 25; + ret = lwip_setsockopt(self->fd, IPPROTO_TCP, TCP_KEEPINTVL, &optval, sizeof(int));//TCP_KEEPINTVL + + optval = 3; + ret = lwip_setsockopt(self->fd, IPPROTO_TCP, TCP_KEEPCNT, &optval, sizeof(int)); + if (ret != 0) { +#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) + int socket_errno = lwip_get_soc_errno(); +#else + int socket_errno = errno; +#endif + mp_raise_OSError(socket_errno); + } + } + break; + } + + #if MICROPY_PY_USOCKET_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); + self->events_callback = MP_OBJ_NULL; + } + } else { + if (self->events_callback == MP_OBJ_NULL) { + usocket_events_add(self); + } + self->events_callback = args[3]; + } + break; + } + #endif + default: + mp_printf(&mp_plat_print, "Warning: lwip.setsockopt() option not implemented\n"); + } + + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_setsockopt); + +void _socket_settimeout(socket_obj_t *sock, uint64_t timeout_ms) { + // Rather than waiting for the entire timeout specified, we wait sock->retries times + // for SOCKET_POLL_US each, checking for a MicroPython interrupt between timeouts. + // with SOCKET_POLL_MS == 100ms, sock->retries allows for timeouts up to 13 years. + // if timeout_ms == UINT64_MAX, wait forever. + sock->retries = (timeout_ms == TIMEOUT_MAX) ? UINT_MAX : timeout_ms * 1000 / SOCKET_POLL_US; + + sock->timeout = timeout_ms/1000; + + struct timeval timeout = { + .tv_sec = 0, + .tv_usec = timeout_ms ? SOCKET_POLL_US : 0 + }; + lwip_setsockopt(sock->fd, SOL_SOCKET, SO_SNDTIMEO, (const void *)&timeout, sizeof(timeout)); + lwip_setsockopt(sock->fd, SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)); + lwip_fcntl(sock->fd, F_SETFL, timeout_ms ? 0 : O_NONBLOCK); +} + +static mp_obj_t socket_settimeout(const mp_obj_t arg0, const mp_obj_t arg1) { + socket_obj_t *self = MP_OBJ_TO_PTR(arg0); + if (arg1 == mp_const_none) { + _socket_settimeout(self, TIMEOUT_MAX); + } else { + #if MICROPY_PY_BUILTINS_FLOAT + _socket_settimeout(self, (uint64_t)(mp_obj_get_float(arg1) * MICROPY_FLOAT_CONST(1000.0))); + #else + _socket_settimeout(self, mp_obj_get_int(arg1) * 1000); + #endif + } + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_2(socket_settimeout_obj, socket_settimeout); + +static mp_obj_t socket_setblocking(const mp_obj_t arg0, const mp_obj_t arg1) { + socket_obj_t *self = MP_OBJ_TO_PTR(arg0); + if (mp_obj_is_true(arg1)) { + _socket_settimeout(self, TIMEOUT_MAX); + } else { + _socket_settimeout(self, 0); + } + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking); + +// XXX this can end up waiting a very long time if the content is dribbled in one character +// at a time, as the timeout resets each time a recvfrom succeeds ... this is probably not +// good behaviour. +static mp_uint_t _socket_read_data(mp_obj_t self_in, void *buf, size_t size, + struct sockaddr *from, socklen_t *from_len, int *errcode) { + socket_obj_t *sock = MP_OBJ_TO_PTR(self_in); + + // A new socket cannot be read from. + if (sock->state == SOCKET_STATE_NEW) { + *errcode = MP_ENOTCONN; + return MP_STREAM_ERROR; + } + + // If the peer closed the connection then the lwIP socket API will only return "0" once + // from lwip_recvfrom and then block on subsequent calls. To emulate POSIX behaviour, + // which continues to return "0" for each call on a closed socket, we set a flag when + // the peer closed the socket. + if (sock->state == SOCKET_STATE_PEER_CLOSED) { + return 0; + } + + unsigned int retries = 0; + if (sock->timeout > 5) + { + retries = ((sock->timeout/5) - 1); + if (!retries) + retries = 1; + } + else + { + retries = sock->retries; + } + + // XXX Would be nicer to use RTC to handle timeouts + for (unsigned int i = 0; i <= retries; ++i) { + // Poll the socket to see if it has waiting data and only release the GIL if it doesn't. + // This ensures higher performance in the case of many small reads, eg for readline. + + if (sock->timeout > 5) + { + unsigned int retries_i = 0; + retries_i = sock->timeout/5; + if (!((retries_i - 1) == retries)) + { + retries = retries_i; + } + } + else + { + retries = sock->retries; + } + + if (sock->timeout > 5) + { + struct timeval timeout = { .tv_sec = 5, .tv_usec = 0 }; + lwip_setsockopt(sock->fd, SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)); + } + + MP_THREAD_GIL_EXIT(); + int r = lwip_recvfrom(sock->fd, buf, size, 0, from, from_len); + MP_THREAD_GIL_ENTER(); + +#if defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) + int socket_errno = lwip_get_soc_errno(); +#elif defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) + int socket_errno = lwip_get_error(sock->fd); +#else + int socket_errno = errno; +#endif + if (r == 0) + { + sock->state = SOCKET_STATE_PEER_CLOSED; + if (socket_errno == ENOTCONN)//recv FIN + { + *errcode = ENOTCONN; + return MP_STREAM_ERROR; + } + } + + if (r >= 0) { + return r; + } + +#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) + int32_t tcpstate = (int32_t)lwip_getTcpState(sock->fd); + if ((tcpstate < 4) && (sock->type == SOCK_STREAM)) + { + if (socket_errno == EWOULDBLOCK) + { + mp_raise_OSError(115); + } + } +#endif + +#if defined(PLAT_EIGEN) + if ((socket_errno != EWOULDBLOCK) && (socket_errno != 62)) +#else + if (socket_errno != EWOULDBLOCK) +#endif + { + *errcode = socket_errno; + return MP_STREAM_ERROR; + } + check_for_exceptions(); + } + + *errcode = sock->retries == 0 ? MP_EWOULDBLOCK : MP_ETIMEDOUT; + return MP_STREAM_ERROR; +} + +mp_obj_t _socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in, + struct sockaddr *from, socklen_t *from_len) { + size_t len = mp_obj_get_int(len_in); + vstr_t vstr; + vstr_init_len(&vstr, len); + + int errcode; + mp_uint_t ret = _socket_read_data(self_in, vstr.buf, len, from, from_len, &errcode); + if (ret == MP_STREAM_ERROR) { + mp_raise_OSError(errcode); + } + + vstr.len = ret; + return mp_obj_new_str_from_vstr(&vstr); +} + +static mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) { + return _socket_recvfrom(self_in, len_in, NULL, NULL); +} +static MP_DEFINE_CONST_FUN_OBJ_2(socket_recv_obj, socket_recv); + +static mp_obj_t socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) { + struct sockaddr from; + socklen_t fromlen = sizeof(from); + + mp_obj_t tuple[2]; + tuple[0] = _socket_recvfrom(self_in, len_in, &from, &fromlen); + + uint8_t *ip = (uint8_t *)&((struct sockaddr_in *)&from)->sin_addr; + mp_uint_t port = lwip_ntohs(((struct sockaddr_in *)&from)->sin_port); + 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); + +int _socket_send(socket_obj_t *sock, const char *data, size_t datalen) { + int sentlen = 0; + for (unsigned int i = 0; i <= sock->retries && sentlen < (int) datalen; i++) { + MP_THREAD_GIL_EXIT(); + int r = lwip_write(sock->fd, data + sentlen, datalen - sentlen); + MP_THREAD_GIL_ENTER(); +#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) + int socket_errno = lwip_get_soc_errno(); +#else + int socket_errno = errno; +#endif + // lwip returns EINPROGRESS when trying to send right after a non-blocking connect + if (r < 0 && socket_errno != EWOULDBLOCK && socket_errno != EINPROGRESS) { + mp_raise_OSError(socket_errno); + //mp_raise_OSError(errno); + } + if (r > 0) { + sentlen += r; + } + check_for_exceptions(); + } + if (sentlen == 0) { + mp_raise_OSError(sock->retries == 0 ? MP_EWOULDBLOCK : MP_ETIMEDOUT); + } + return sentlen; +} + +static mp_obj_t socket_send(const mp_obj_t arg0, const mp_obj_t arg1) { + socket_obj_t *sock = MP_OBJ_TO_PTR(arg0); + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(arg1, &bufinfo, MP_BUFFER_READ); + int r = _socket_send(sock, bufinfo.buf, bufinfo.len); + return mp_obj_new_int(r); +} +static MP_DEFINE_CONST_FUN_OBJ_2(socket_send_obj, socket_send); + +static mp_obj_t socket_sendall(const mp_obj_t arg0, const mp_obj_t arg1) { + // XXX behaviour when nonblocking (see extmod/modlwip.c) + // XXX also timeout behaviour. + socket_obj_t *sock = MP_OBJ_TO_PTR(arg0); + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(arg1, &bufinfo, MP_BUFFER_READ); + int r = _socket_send(sock, bufinfo.buf, bufinfo.len); + if (r < (int) bufinfo.len) { + mp_raise_OSError(MP_ETIMEDOUT); + } + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_2(socket_sendall_obj, socket_sendall); + +static mp_obj_t socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_in) { + socket_obj_t *self = MP_OBJ_TO_PTR(self_in); + + // get the buffer to send + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(data_in, &bufinfo, MP_BUFFER_READ); + + // create the destination address + struct sockaddr_in to; + to.sin_len = sizeof(to); + to.sin_family = AF_INET; + to.sin_port = lwip_htons(netutils_parse_inet_addr(addr_in, (uint8_t *)&to.sin_addr, NETUTILS_BIG)); + + // send the data + for (unsigned int i = 0; i <= self->retries; i++) { + MP_THREAD_GIL_EXIT(); + int ret = lwip_sendto(self->fd, bufinfo.buf, bufinfo.len, 0, (struct sockaddr *)&to, sizeof(to)); + MP_THREAD_GIL_ENTER(); + if (ret > 0) { + return mp_obj_new_int_from_uint(ret); + } +#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) + int socket_errno = lwip_get_soc_errno(); +#else + int socket_errno = errno; +#endif + if (ret == -1 && socket_errno != EWOULDBLOCK) { + mp_raise_OSError(socket_errno); + //mp_raise_OSError(errno); + } + check_for_exceptions(); + } + mp_raise_OSError(MP_ETIMEDOUT); +} +static MP_DEFINE_CONST_FUN_OBJ_3(socket_sendto_obj, socket_sendto); + +static mp_obj_t socket_fileno(const mp_obj_t arg0) { + socket_obj_t *self = MP_OBJ_TO_PTR(arg0); + return mp_obj_new_int(self->fd); +} +static MP_DEFINE_CONST_FUN_OBJ_1(socket_fileno_obj, socket_fileno); + +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); + +static mp_uint_t socket_stream_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { + return _socket_read_data(self_in, buf, size, NULL, NULL, errcode); +} + +static mp_uint_t socket_stream_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { + socket_obj_t *sock = self_in; + for (unsigned int i = 0; i <= sock->retries; i++) { + MP_THREAD_GIL_EXIT(); + int r = lwip_write(sock->fd, buf, size); + MP_THREAD_GIL_ENTER(); + if (r > 0) { + return r; + } +#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) + int socket_errno = lwip_get_soc_errno(); +#else + int socket_errno = errno; +#endif + // lwip returns MP_EINPROGRESS when trying to write right after a non-blocking connect + if (r < 0 && socket_errno != EWOULDBLOCK && socket_errno != EINPROGRESS) { + *errcode = socket_errno; + return MP_STREAM_ERROR; + } + check_for_exceptions(); + } + *errcode = sock->retries == 0 ? MP_EWOULDBLOCK : MP_ETIMEDOUT; + return MP_STREAM_ERROR; +} + +static mp_uint_t socket_stream_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { + socket_obj_t *socket = self_in; + if (request == MP_STREAM_POLL) { + if (socket->fd == -1) { + return MP_STREAM_POLL_NVAL; + } + + fd_set rfds; + FD_ZERO(&rfds); + fd_set wfds; + FD_ZERO(&wfds); + fd_set efds; + FD_ZERO(&efds); + struct timeval timeout = { .tv_sec = 0, .tv_usec = 0 }; + if (arg & MP_STREAM_POLL_RD) { + FD_SET(socket->fd, &rfds); + } + if (arg & MP_STREAM_POLL_WR) { + FD_SET(socket->fd, &wfds); + } + if (arg & MP_STREAM_POLL_HUP) { + FD_SET(socket->fd, &efds); + } + + int r = select((socket->fd) + 1, &rfds, &wfds, &efds, &timeout); + if (r < 0) { + *errcode = MP_EIO; + return MP_STREAM_ERROR; + } + + mp_uint_t ret = 0; + if (FD_ISSET(socket->fd, &rfds)) { + ret |= MP_STREAM_POLL_RD; + } + if (FD_ISSET(socket->fd, &wfds)) { + ret |= MP_STREAM_POLL_WR; + } + if (FD_ISSET(socket->fd, &efds)) { + ret |= MP_STREAM_POLL_HUP; + } + + // New (unconnected) sockets are writable and have HUP set. + if (socket->state == SOCKET_STATE_NEW) { + ret |= (arg & MP_STREAM_POLL_WR) | MP_STREAM_POLL_HUP; + } + + return ret; + } else if (request == MP_STREAM_CLOSE) { + if (socket->fd >= 0) { + #if MICROPY_PY_USOCKET_EVENTS + if (socket->events_callback != MP_OBJ_NULL) { + usocket_events_remove(socket); + socket->events_callback = MP_OBJ_NULL; + } + #endif + int ret = lwip_close(socket->fd); +#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) + int socket_errno = lwip_get_soc_errno(); +#else + int socket_errno = errno; +#endif + if (ret != 0) { + *errcode = errno; + *errcode = socket_errno; + return MP_STREAM_ERROR; + } + socket->fd = -1; + } + return 0; + } + + *errcode = MP_EINVAL; + return MP_STREAM_ERROR; +} + +#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) +static mp_obj_t socket_getstate(const mp_obj_t self_in) +{ + socket_obj_t *self = MP_OBJ_TO_PTR(self_in); + int32_t tcpstate = (int32_t)lwip_getTcpState(self->fd); + return mp_obj_new_int(tcpstate); +} +static MP_DEFINE_CONST_FUN_OBJ_1(socket_getstate_obj, socket_getstate); +#endif + + +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_sendto), MP_ROM_PTR(&socket_sendto_obj) }, + { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&socket_recv_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) }, +#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) + { MP_ROM_QSTR(MP_QSTR_getsocketsta), MP_ROM_PTR(&socket_getstate_obj) }, +#endif + { MP_ROM_QSTR(MP_QSTR_fileno), MP_ROM_PTR(&socket_fileno_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); + +static const mp_stream_p_t socket_stream_p = { + .read = socket_stream_read, + .write = socket_stream_write, + .ioctl = socket_stream_ioctl +}; + +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 quec_socket_getaddrinfo(size_t n_args, const mp_obj_t *args) { + // TODO support additional args beyond the first two + + struct addrinfo *res = NULL; + _socket_getaddrinfo2(args[0], args[1], &res); + mp_obj_t ret_list = mp_obj_new_list(0, NULL); + + for (struct addrinfo *resi = res; resi; resi = resi->ai_next) + { + mp_obj_t addrinfo_objs[5] = { + mp_obj_new_int(resi->ai_family), + mp_obj_new_int(resi->ai_socktype), + mp_obj_new_int(resi->ai_protocol), + mp_obj_new_str(resi->ai_canonname, strlen(resi->ai_canonname)), + mp_const_none + }; + + if (resi->ai_family == AF_INET) + { + char buf[16]; + struct sockaddr_in *addr = (struct sockaddr_in *)resi->ai_addr; + // This looks odd, but it's really just a u32_t + ip_addr_t ip4_addr = { .u_addr.ip4.addr = addr->sin_addr.s_addr }; + ipaddr_ntoa_r(&ip4_addr, buf, sizeof(buf)); + mp_obj_t inaddr_objs[2] = { + mp_obj_new_str(buf, strlen(buf)), + mp_obj_new_int(ntohs(addr->sin_port)) + }; + addrinfo_objs[4] = mp_obj_new_tuple(2, inaddr_objs); + } + else if (resi->ai_family == AF_INET6) + { + char ip6_addr_buf[128] = {0}; + struct sockaddr_in6 *addr = (struct sockaddr_in6 *)resi->ai_addr; + inet_ntop(AF_INET6, &addr->sin6_addr, ip6_addr_buf, sizeof(ip6_addr_buf)); + mp_obj_t inaddr_objs[2] = { + mp_obj_new_str(ip6_addr_buf, strlen(ip6_addr_buf)), + mp_obj_new_int(ntohs(addr->sin6_port)) + }; + addrinfo_objs[4] = mp_obj_new_tuple(2, inaddr_objs); + } + + mp_obj_list_append(ret_list, mp_obj_new_tuple(5, addrinfo_objs)); + } + + if (res) { + lwip_freeaddrinfo(res); + } + return ret_list; +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(quec_socket_getaddrinfo_obj, 2, 6, quec_socket_getaddrinfo); + +static mp_obj_t quec_socket_initialize() { + static int initialized = 0; + if (!initialized) { + initialized = 1; + } + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_0(quec_socket_initialize_obj, quec_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___init__), MP_ROM_PTR(&quec_socket_initialize_obj) }, + { MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&socket_type) }, + { MP_ROM_QSTR(MP_QSTR_getaddrinfo), MP_ROM_PTR(&quec_socket_getaddrinfo_obj) }, + + { MP_ROM_QSTR(MP_QSTR_AF_INET), MP_ROM_INT(AF_INET) }, + { MP_ROM_QSTR(MP_QSTR_AF_INET6), MP_ROM_INT(AF_INET6) }, + { MP_ROM_QSTR(MP_QSTR_SOCK_STREAM), MP_ROM_INT(SOCK_STREAM) }, + { MP_ROM_QSTR(MP_QSTR_SOCK_DGRAM), MP_ROM_INT(SOCK_DGRAM) }, + { MP_ROM_QSTR(MP_QSTR_SOCK_RAW), MP_ROM_INT(SOCK_RAW) }, + { MP_ROM_QSTR(MP_QSTR_IPPROTO_TCP), MP_ROM_INT(IPPROTO_TCP) }, + { MP_ROM_QSTR(MP_QSTR_IPPROTO_UDP), MP_ROM_INT(IPPROTO_UDP) }, + { MP_ROM_QSTR(MP_QSTR_IPPROTO_TCP_SER), MP_ROM_INT(7) }, + { MP_ROM_QSTR(MP_QSTR_TCP_CUSTOMIZE_PORT), MP_ROM_INT(8) }, + { MP_ROM_QSTR(MP_QSTR_IPPROTO_IP), MP_ROM_INT(IPPROTO_IP) }, + { MP_ROM_QSTR(MP_QSTR_SOL_SOCKET), MP_ROM_INT(SOL_SOCKET) }, + { MP_ROM_QSTR(MP_QSTR_TCP_KEEPALIVE), MP_ROM_INT(TCP_KEEPALIVE) }, + { MP_ROM_QSTR(MP_QSTR_SO_REUSEADDR), MP_ROM_INT(SO_REUSEADDR) }, +}; + +static MP_DEFINE_CONST_DICT(mp_module_socket_globals, mp_module_socket_globals_table); + +const mp_obj_module_t mp_module_usocket = { + .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 +// this will not conflict with the common implementation provided by +// extmod/mod{lwip,usocket}.c. +MP_REGISTER_MODULE(MP_QSTR_usocket, mp_module_usocket); + +#endif //MICROPY_QPY_MODULE_USOCKET diff --git a/ports/quectel/modules/_boot.py b/ports/quectel/modules/_boot.py new file mode 100644 index 0000000000000..08b55c4f39ae5 --- /dev/null +++ b/ports/quectel/modules/_boot.py @@ -0,0 +1,144 @@ +# Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. +# +# 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. + +import uos +import ujson +import dial + +''' +Mark.Zhu - 2022/12/02 +Added the littlefs2 mount function,it will be called after a failed attempt to mount littlefs1 +''' +# global datacall_flag +datacall_flag = 1 + +def _auto_activate_pdpcontext(): + if "datacall_config.json" not in uos.listdir('/usr'): + # raise ValueError("Not found datacall_config.json.") + dial.setAutoConnect(1, 1) + dial.setAsynMode(1) + dial.start(1, 0, '', '', '', 0) + dial.setAsynMode(0) + else: + retval = dial.getPdpRange() + max_profile = retval[1] + + with open("/usr/datacall_config.json", "r", encoding='utf-8') as fd: + try: + datacall_config = ujson.load(fd) + if not isinstance(datacall_config, dict): + raise ValueError("The format of the datacall_config.json is incorrect.") + + for profile_id in range(1, max_profile+1): + value_of_key_profileid = datacall_config.get(str(profile_id), None) + if value_of_key_profileid is not None: + if not isinstance(value_of_key_profileid, dict): + raise ValueError("The format of the datacall_config.json is incorrect.") + value_of_key_autoActivate = value_of_key_profileid.get("autoActivate", 0) + value_of_key_autoConnect = value_of_key_profileid.get("autoConnect", 0) + if value_of_key_autoConnect==1: + dial.setAutoConnect(profile_id, value_of_key_autoConnect) + if value_of_key_autoActivate == 1: + dial.setAsynMode(1) + ret = -1 + repeat_count = 2 + while (ret == -1) and (repeat_count >= 0): + repeat_count -= 1 + ret = dial.start(profile_id, 0, '', '', '', 0) + if ret == -1: + print('Activation of the {} PDP Context failed.'.format(profile_id)) + dial.setAsynMode(0) + else: + pass + except Exception: + raise ValueError("The format of the datacall_config.json is incorrect.") + + +def _check_data_call(): + retval = dial.getPdpRange() + min = retval[0] + max = retval[1] + + for pdp in range(min, max+1): + nw_sta = dial.getInfo(pdp, 2) + if (nw_sta != -1) and (nw_sta[2][0] == 0) and (nw_sta[3][0] == 0): + continue + elif (nw_sta != -1) and ((nw_sta[2][0] == 1) or (nw_sta[3][0] == 1)): + return 1 + return 0 + + +def _repl_enable(): + global datacall_flag + if "system_config.json" in uos.listdir("/usr/"): + with open("/usr/system_config.json", "r", encoding='utf-8') as fd: + try: + json_data = ujson.load(fd) + repl_flag = json_data.get("replFlag", 0) + datacall_flag = json_data.get("datacallFlag", 1) + repl_pswd = json_data.get("replPswd",None) + + import misc + if repl_pswd: + misc.replUpdatePassswd(repl_pswd,repl_pswd) + misc.replEnable(repl_flag, repl_pswd) + else: + misc.replEnable(repl_flag) + except ValueError: + with open("/usr/system_config.json", "w", encoding='utf-8') as fdw: + new_json_data = ujson.dumps({"replFlag": 0, "datacallFlag": datacall_flag}) + fdw.write(new_json_data) + else: + with open("/usr/system_config.json", "w+", encoding='utf-8') as fd: + repl_data = ujson.dumps({"replFlag": 0}) + fd.write(repl_data) + +try: + udev = None + bdev = None + try: + from uos import VfsLfs1 as VfsLfs + except Exception: + from uos import VfsLfs2 as VfsLfs + + udev = uos.FlashDevice('customer_fs', 4096) + try: + uos.mount(udev, '/usr') + except Exception as e: + if 'ENODEV' in str(e): + VfsLfs.mkfs(udev) + uos.mount(udev, '/usr') + else: + raise ValueError("LFS usr mount fail".format(e)) + + bdev = uos.FlashDevice('customer_backup_fs', 4096) + try: + uos.mount(bdev, '/bak') + except Exception as e: + if 'ENODEV' in str(e): + VfsLfs.mkfs(bdev) + uos.mount(bdev, '/bak') + else: + raise ValueError("LFS bak mount fail".format(e)) + + +except Exception: + print('error ocurs in boot step.') + +finally: + _repl_enable() + if datacall_flag == 1: + ret = _check_data_call() + if ret == 0: + _auto_activate_pdpcontext() diff --git a/ports/quectel/modules/app_fota.py b/ports/quectel/modules/app_fota.py new file mode 100644 index 0000000000000..fac458ac6990f --- /dev/null +++ b/ports/quectel/modules/app_fota.py @@ -0,0 +1,33 @@ +# Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. +# +# 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. + +#!python3 +# -*- coding:utf-8 -*- + +import app_fota_download +import app_fota_updater +from app_fota_mount import AppFotaPkgMount +class new(object): + def __init__(self): + self.app_fota_pkg_mount = AppFotaPkgMount() + self.app_fota_pkg_mount.mount_disk() + def download(self, url, file_name, headers=None): + return app_fota_download.download(url, file_name, headers) + def bulk_download(self, info=[], headers=None): + return app_fota_download.bulk_download(info, headers) + def set_update_flag(self): + app_fota_download.set_update_flag() + def update(self): + return app_fota_updater.update() + \ No newline at end of file diff --git a/ports/quectel/modules/app_fota_download.py b/ports/quectel/modules/app_fota_download.py new file mode 100644 index 0000000000000..dc57e95462d73 --- /dev/null +++ b/ports/quectel/modules/app_fota_download.py @@ -0,0 +1,212 @@ +# Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. +# +# 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. + +#!python3 +# -*- coding:utf-8 -*- + +import uos +import request +import ujson +import ql_fs +from app_fota_mount import AppFotaPkgMount +app_fota_pkg_mount = AppFotaPkgMount() + +def get_updater_dir(): + return app_fota_pkg_mount.fota_dir + '/usr/.updater' + +def get_download_stat_file(): + return app_fota_pkg_mount.fota_dir + '/usr/.updater/download.stat' + +def get_update_flag_file(): + return app_fota_pkg_mount.fota_dir + '/usr/.updater/update.flag' + +updater_dir = get_updater_dir() +download_stat_file = get_download_stat_file() +update_flag_file = get_update_flag_file() + + +def _get_download_stat_by_file(file_name): + try: + if not ql_fs.path_exists(get_download_stat_file()): + return None + + fp = open(get_download_stat_file(), 'rt') + if not fp: + return None + + fr = fp.read() + fp.close() + if not fr: + return None + + download_stat = ujson.loads(fr) + for item in download_stat: + if item['name'].lower() == file_name.lower(): + return item + return None + except Exception as e: + return None + + +def _get_download_stat(): + try: + if not ql_fs.path_exists(get_download_stat_file()): + return None + + fp = open(get_download_stat_file(), 'rt') + if not fp: + return None + + fr = fp.read() + fp.close() + if not fr: + return None + + download_stat = ujson.loads(fr) + return download_stat + except Exception as e: + print("get download stat error: "+str(e)) + return None + + +def get_download_stat(): + return _get_download_stat() + + +def _fetch(url, fetched_size, headers=None): + if headers is None or not isinstance(headers, dict): + request_headers = {} + else: + request_headers = headers + request_headers['Range'] = 'bytes={}-'.format(fetched_size) + return request.get(url, headers=request_headers) + + +def _update_download_stat(url, file_name, total_size): + need_append_stat = 1 + download_stat = _get_download_stat() + if download_stat: + for item in download_stat: + if item['name'].lower() == file_name.lower(): + item['url'] = url + item['total_size'] = total_size + need_append_stat = 0 + break + else: + download_stat = [] + + if need_append_stat: + single_download_stat = {} + single_download_stat['url'] = url + single_download_stat['name'] = file_name + single_download_stat['total_size'] = total_size + download_stat.append(single_download_stat) + + json_str = ujson.dumps(download_stat) + fp = open(get_download_stat_file(), 'wt') + fp.write(json_str) + fp.close() + + +def update_download_stat(url, file_name, total_size): + _update_download_stat(url, file_name, total_size) + + +def delete_update_file(file_name): + download_stat = _get_download_stat() + if download_stat: + for item in download_stat[:]: + if item['name'].lower() == file_name.lower(): + download_stat.remove(item) + json_str = ujson.dumps(download_stat) + fp = open(get_download_stat_file(), 'wt') + fp.write(json_str) + fp.close() + + +def download(url, file_name, headers=None): + download_file_name = get_updater_dir() + file_name + ql_fs.mkdirs(ql_fs.path_dirname(download_file_name)) + + single_download_stat = _get_download_stat_by_file(file_name) + if single_download_stat: + if not ql_fs.path_exists(download_file_name): + fetched_size = 0 + else: + fetched_size = ql_fs.path_getsize(download_file_name) + + if fetched_size == single_download_stat['total_size']: + return 0 + else: + fetched_size = 0 + + r = _fetch(url, fetched_size, headers) + if r.status_code == 200 or r.status_code == 206: + total_size = -1 + need_refresh_stat_again = 0 + file_open_mode = '' + if not single_download_stat: + total_size = 'unknown' + _update_download_stat(url, file_name, total_size) + file_open_mode = 'wb+' + else: + file_open_mode = 'ab+' + + fp = open(download_file_name, file_open_mode) + content = r.content + + try: + while True: + c = next(content) + length = len(c) + for i in range(0, length, 4096): + fp.write(c[i:i + 4096]) + except StopIteration: + fp.close() + + r.close() + else: + fp.close() + uos.remove(download_file_name) + r.close() + return -1 + + total_size = ql_fs.path_getsize(download_file_name) + _update_download_stat(url, file_name, total_size) + + return 0 + else: + r.close() + return -1 + + +def bulk_download(info=None, headers=None): + if info is None: + info = [] + fail_result = [] + for item in info: + url = item['url'] + file_name = item['file_name'] + if download(url, file_name, headers) == -1: + fail_result.append(item) + if len(fail_result): + return fail_result + return None + + +def set_update_flag(): + ql_fs.mkdirs(ql_fs.path_dirname(get_update_flag_file())) + fp = open(get_update_flag_file(), 'wb') + fp.close() + diff --git a/ports/quectel/modules/app_fota_mount.py b/ports/quectel/modules/app_fota_mount.py new file mode 100644 index 0000000000000..3b98052f75a56 --- /dev/null +++ b/ports/quectel/modules/app_fota_mount.py @@ -0,0 +1,49 @@ +import uos + + +class AppFotaPkgMount(object): + __instance = None + __mount_state = False + __can_mount = False + def __new__(cls, *args, **kwargs): + if cls.__instance is None: + cls.__instance = object.__new__(cls, *args, **kwargs) + return cls.__instance + + def __init__(self): + self.__fota_dir = "/fota" + + @property + def mount_state(self): + return self.__mount_state + + @property + def can_mount(self): + return self.__can_mount + + @property + def fota_dir(self): + if not self.can_mount: + return "" + else: + return self.__fota_dir + + def mount_disk(self): + try: + if not self.mount_state: + fota_pkg = uos.VfsTemp("customer_temp_fs") + uos.mount(fota_pkg, self.__fota_dir) + except Exception as e: + self.__mount_state = False + self.__can_mount = False + else: + self.__mount_state = True + self.__can_mount = True + + def umount_disk(self): + if self.mount_state: + uos.umount(self.fota_dir) + self.__mount_state = False + + def get_fota_file_name(self, path): + return self.fota_dir + path \ No newline at end of file diff --git a/ports/quectel/modules/app_fota_updater.py b/ports/quectel/modules/app_fota_updater.py new file mode 100644 index 0000000000000..9214090a1b73c --- /dev/null +++ b/ports/quectel/modules/app_fota_updater.py @@ -0,0 +1,91 @@ +# Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. +# +# 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. + +#!python3 +# -*- coding:utf-8 -*- + +import uos +import ujson +import ql_fs +import checksum +from app_fota_mount import AppFotaPkgMount +app_fota_pkg_mount = AppFotaPkgMount() + +def get_updater_dir(): + return app_fota_pkg_mount.fota_dir+ '/usr/.updater' + +def get_download_stat_file(): + return app_fota_pkg_mount.fota_dir+'/usr/.updater/download.stat' + +def get_update_flag_file(): + return app_fota_pkg_mount.fota_dir+'/usr/.updater/update.flag' + +updater_dir = get_updater_dir() +download_stat_file = get_download_stat_file() +download_stat_file_max_size = 16384 +update_flag_file = get_update_flag_file() + +def _check_update_flag(): + try: + if ql_fs.path_exists(get_update_flag_file()): + return 1 + else: + return 0 + except Exception as e: + return 0 + +def update(): + if _check_update_flag(): + try: + if not ql_fs.path_exists(get_download_stat_file()): + return -1 + + fp = open(get_download_stat_file(), 'rt') + if not fp: + return -1 + + fr = fp.read(download_stat_file_max_size) + fp.close() + if not fr: + return -1 + download_stat = ujson.loads(fr) + print(download_stat) + download_stat_tmp = download_stat[:] + print(download_stat_tmp) + for item in download_stat: + file_name = item['name'] + download_file_name = get_updater_dir() + file_name + if ql_fs.path_exists(download_file_name): + ql_fs.mkdirs(ql_fs.path_dirname(file_name)) + ql_fs.file_copy(file_name, download_file_name) + checksum.update(file_name) + download_stat_tmp.remove(item) + json_str = ujson.dumps(download_stat_tmp) + fp = open(get_download_stat_file(), 'wt') + if not fp: + return -1 + fp.write(json_str) + fp.close() + uos.remove(download_file_name) + uos.remove(get_update_flag_file()) + uos.remove(get_download_stat_file()) + ql_fs.rmdirs(get_updater_dir()) + app_fota_pkg_mount.umount_disk() + return 0 + + except Exception as e: + return -1 + else: + app_fota_pkg_mount.umount_disk() + return -1 \ No newline at end of file diff --git a/ports/quectel/modules/checkNet.py b/ports/quectel/modules/checkNet.py new file mode 100644 index 0000000000000..b19a69eb8d880 --- /dev/null +++ b/ports/quectel/modules/checkNet.py @@ -0,0 +1,231 @@ +# Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. +# +# 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. + + +''' +jayceon 2020/12/31 +''' + +import sim +import net +import utime +import modem +import dial +import dataCall +# from misc import Power + +class CheckNetwork(): + def __init__(self, proj_name, proj_version): + self.PROJECT_NAME = proj_name + self.PROJECT_VERSION = proj_version + self.FIRMWARE_VERSION = modem.getDevFwVersion() + # self.POWERON_REASON = Power.powerOnReason() + + def poweron_print_once(self): + sim_sta = sim.getStatus() + print('==================================================') + print('PROJECT_NAME : {}'.format(self.PROJECT_NAME)) + print('PROJECT_VERSION : {}'.format(self.PROJECT_VERSION)) + print('FIRMWARE_VERSION : {}'.format(self.FIRMWARE_VERSION)) + # print('POWERON_REASON : {}'.format(self.POWERON_REASON)) + print('SIM_CARD_STATUS : {}'.format(sim_sta)) + print('==================================================') + + @staticmethod + def check_datacall_status(): + retval = dial.getPdpRange() + min = retval[0] + max = retval[1] + for pdp in range(min, max+1): + datacall_sta = dataCall.getInfo(pdp, 2) + if (datacall_sta != -1) and ((datacall_sta[2][0] == 1) or (datacall_sta[3][0] == 1)): + return 1 + elif (datacall_sta != -1) and (datacall_sta[2][0] == 0) and (datacall_sta[3][0] == 0): + continue + return 0 + + ''' + return format: stagecode, subcode, time + stagecode - + 1:Currently in the stage of getting SIM card state + 2:Currently in the stage of getting network state + 3:Currently in the stage of getting datacall state + subcode - + when stagecode = 1, subcode represents the state of the SIM card + when stagecode = 2, subcode represents the state of the network + when stagecode = 3, subcode represents the state of the datacall + ''' + def wait_network_connected(self, timeout_s=60): + if (timeout_s < 1) or (timeout_s > 3600): + raise OSError("timeout_s should be in [1, 3600]s!") + timeout_ms = timeout_s * 1000 + + ''' + stage_code = 1 + while True: + sim_sta = sim.getStatus() + if sim_sta == 1: + break + elif sim_sta == 0: + return stage_code, sim_sta + elif (sim_sta == 18) or (sim_sta == 20) or (sim_sta == 21): + utime.sleep_ms(100) + timeout_ms -= 100 + if timeout_ms <= 0: + return stage_code, sim_sta + else: + return stage_code, sim_sta + + stage_code = 2 + while True: + net_sta = net.getState() + if net_sta == -1: + utime.sleep_ms(100) + timeout_ms -= 100 + if timeout_ms <= 0: + return stage_code, -1 + else: + if (net_sta[1][0] == 1) or (net_sta[1][0] == 5): + break + else: + utime.sleep_ms(100) + timeout_ms -= 100 + if timeout_ms <= 0: + return stage_code, net_sta[1][0] + + stage_code = 3 + while True: + datacall_sta = self.check_datacall_status() + if datacall_sta == 1: + return stage_code, datacall_sta + else: + utime.sleep_ms(100) + timeout_ms -= 100 + if timeout_ms <= 0: + return stage_code, datacall_sta + ''' + current_time = utime.ticks_ms() + last_time = current_time + stage_code = 1 + while True: + sim_sta = sim.getStatus() + if sim_sta == 1: + break + else: + utime.sleep_ms(100) + current_time = utime.ticks_ms() + timeout_ms -= utime.ticks_diff(current_time, last_time) + last_time = current_time + if timeout_ms <= 0: + return stage_code, sim_sta + + current_time = utime.ticks_ms() + last_time = current_time + stage_code = 2 + while True: + net_sta = net.getState() + if net_sta == -1: + utime.sleep_ms(100) + #timeout_ms -= 100 + current_time = utime.ticks_ms() + timeout_ms -= utime.ticks_diff(current_time, last_time) + last_time = current_time + if timeout_ms <= 0: + return stage_code, -1 + else: + if (net_sta[1][0] == 1) or (net_sta[1][0] == 5): + break + else: + utime.sleep_ms(100) + #timeout_ms -= 100 + current_time = utime.ticks_ms() + timeout_ms -= utime.ticks_diff(current_time, last_time) + last_time = current_time + if timeout_ms <= 0: + return stage_code, net_sta[1][0] + + current_time = utime.ticks_ms() + last_time = current_time + stage_code = 3 + while True: + datacall_sta = self.check_datacall_status() + if datacall_sta == 1: + return stage_code, datacall_sta + else: + utime.sleep_ms(100) + #timeout_ms -= 100 + current_time = utime.ticks_ms() + timeout_ms -= utime.ticks_diff(current_time, last_time) + last_time = current_time + if timeout_ms <= 0: + return stage_code, datacall_sta + + +def wait_network_connected(timeout_s=60): + if (timeout_s < 1) or (timeout_s > 3600): + raise OSError("timeout_s should be in [1, 3600]s!") + timeout_ms = timeout_s * 1000 + + current_time = utime.ticks_ms() + last_time = current_time + stage_code = 1 + while True: + sim_sta = sim.getStatus() + if sim_sta == 1: + break + else: + utime.sleep_ms(100) + current_time = utime.ticks_ms() + timeout_ms -= utime.ticks_diff(current_time, last_time) + last_time = current_time + if timeout_ms <= 0: + return stage_code, sim_sta + + current_time = utime.ticks_ms() + last_time = current_time + stage_code = 2 + while True: + net_sta = net.getState() + if net_sta == -1: + utime.sleep_ms(100) + current_time = utime.ticks_ms() + timeout_ms -= utime.ticks_diff(current_time, last_time) + last_time = current_time + if timeout_ms <= 0: + return stage_code, -1 + else: + if (net_sta[1][0] == 1) or (net_sta[1][0] == 5): + break + else: + utime.sleep_ms(100) + current_time = utime.ticks_ms() + timeout_ms -= utime.ticks_diff(current_time, last_time) + last_time = current_time + if timeout_ms <= 0: + return stage_code, net_sta[1][0] + + current_time = utime.ticks_ms() + last_time = current_time + stage_code = 3 + while True: + datacall_sta = CheckNetwork.check_datacall_status() + if datacall_sta == 1: + return stage_code, datacall_sta + else: + utime.sleep_ms(100) + current_time = utime.ticks_ms() + timeout_ms -= utime.ticks_diff(current_time, last_time) + last_time = current_time + if timeout_ms <= 0: + return stage_code, datacall_sta diff --git a/ports/quectel/modules/checksum.py b/ports/quectel/modules/checksum.py new file mode 100644 index 0000000000000..9478cecb26235 --- /dev/null +++ b/ports/quectel/modules/checksum.py @@ -0,0 +1,157 @@ +# Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. +# +# 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. + +# !python3 +# -*- coding:utf-8 -*- + +import ujson +import uos +import file_crc32 +import ql_fs + +checksum_file = '/usr/checksum.json' +checksum_file_max_size = 16384 +backup_checksum_file = '/bak/checksum.json' + + +class _checkError(Exception): + def __init__(self, value): + self.value = value + + def __str__(self): + return repr(self.value) + + +def check(): + if not ql_fs.path_exists(checksum_file): + if not ql_fs.path_exists(backup_checksum_file): + raise _checkError('%s not exist' % checksum_file) + else: + ql_fs.mkdirs(ql_fs.path_dirname(checksum_file)) + ql_fs.file_copy(checksum_file, backup_checksum_file) + + fp = open(checksum_file, 'rt+') + fp.seek(0) + fr = fp.read(checksum_file_max_size) + fp.close() + if not fr: + raise _checkError('%s is empty' % checksum_file) + return fr + + +def retrieve(file_name): + # Pawn 2021-01-14 for JIRA STASR3601-2428 begin + if not file_name.startswith("/"): + file_name = "/" + file_name + # Pawn 2021-01-14 for JIRA STASR3601-2428 end + + json_str = check() + checksum = ujson.loads(json_str) + for item in checksum: + if item['name'].lower() == file_name.lower(): + return item['crc32'] + return None + + +def _flush_checksum(checksum=[], file_name=checksum_file): + json_str = ujson.dumps(checksum) + fp = open(file_name, 'wt+') + fp.seek(0) + wl = fp.write(json_str) + fp.close() + if wl > 0: + return checksum + return None + + +def bak_update(file_name): + # add by Jaxsen xu + checksum = ql_fs.read_json(backup_checksum_file) + + if not file_name.startswith("/"): + file_name = "/" + file_name + + src_file = file_name[file_name.find("/", 1):] + exist_file = False + for item in checksum: + if item['name'].lower() == src_file.lower(): + exist_file = True + file_crc32_value = file_crc32.calc(file_name) + item['crc32'] = file_crc32_value + if not exist_file: + checksum.append(dict(name=src_file.lower(), crc32=file_crc32.calc(file_name))) + return _flush_checksum(checksum, file_name=file_name[:file_name.find("/", 1)] + "/checksum.json") + + +def usr_update(file_name): + try: + data = ql_fs.read_json(checksum_file) + if data is not None: + exist_file = False + for item in data: + if item['name'].lower() == file_name.lower(): + exist_file = True + item['crc32'] = file_crc32.calc(file_name) + if not exist_file: + data.append(dict(name=file_name.lower(), crc32=file_crc32.calc(file_name))) + return ql_fs.touch(checksum_file, data) + return None + except Exception as e: + return None + + +def update(file_name): + try: + json_str = check() + checksum = ujson.loads(json_str) + + # Pawn 2021-01-14 for JIRA STASR3601-2428 begin + if not file_name.startswith("/"): + file_name = "/" + file_name + # Pawn 2021-01-14 for JIRA STASR3601-2428 end + + for item in checksum: + if item['name'].lower() == file_name.lower(): + file_crc32_value = file_crc32.calc(file_name) + if file_crc32_value: + item['crc32'] = file_crc32_value + return _flush_checksum(checksum) + return None + except Exception: + return None + + +def bulk_update(file_name_list=[]): + try: + json_str = check() + checksum = ujson.loads(json_str) + need_update = 0 + + for file_name in file_name_list: + # Pawn 2021-01-14 for JIRA STASR3601-2428 begin + if not file_name.startswith("/"): + file_name = "/" + file_name + # Pawn 2021-01-14 for JIRA STASR3601-2428 end + for item in checksum: + if item['name'].lower() == file_name.lower(): + file_crc32_value = file_crc32.calc(file_name) + if file_crc32_value: + item['crc32'] = file_crc32_value + need_update = 1 + break + if need_update: + return _flush_checksum(checksum) + return None + except Exception: + return None diff --git a/ports/quectel/modules/dataCall.py b/ports/quectel/modules/dataCall.py new file mode 100644 index 0000000000000..16ea6c6fa88e8 --- /dev/null +++ b/ports/quectel/modules/dataCall.py @@ -0,0 +1,284 @@ +# -*- coding:utf-8 -*- +# Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. +# +# 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. + + +""" +jayceon 2021/03/23 +""" + +import dial + +def setAutoActivate(profileID, enable,cur_simid=None): + + """ + if profileID < 1 or profileID > 3: + raise ValueError("invalid value, profileID should be in [1,3].") + if enable != 0 and enable != 1: + raise ValueError("invalid value, enable should be 0 or 1.") + if cur_simid != None and cur_simid != 0 and cur_simid != 1: + raise ValueError("invalid value, enable should be 0 or 1.") + + if "datacall_config.json" in uos.listdir('/usr'): + with open("/usr/datacall_config.json", "r", encoding='utf-8') as fd: + try: + datacall_config = ujson.load(fd) + if not isinstance(datacall_config, dict): + raise ValueError("The format of the datacall_config.json is incorrect.") + + value_of_key_profileid = datacall_config.get(str(profileID), None) + if value_of_key_profileid is not None: + if not isinstance(value_of_key_profileid, dict): + raise ValueError("The format of the datacall_config.json is incorrect.") + if cur_simid ==1: + datacall_config[str(profileID)]["autoActivate_1"] = enable + else: + datacall_config[str(profileID)]["autoActivate"] = enable + # value_of_key_autoConnect = value_of_key_profileid.get("autoConnect", 0) + # datacall_config[str(profileID)] = {"autoActivate": enable, "autoConnect": value_of_key_autoConnect} + else: + # datacall_config[str(profileID)] = {"autoActivate": enable, "autoConnect": 0} + if cur_simid ==1: + datacall_config[str(profileID)] = {"autoActivate": 0, "autoConnect": 0,"autoActivate_1": enable} + else: + datacall_config[str(profileID)] = {"autoActivate": enable,"autoConnect": 0} + except Exception: + raise ValueError("The format of the datacall_config.json is incorrect.") + with open("/usr/datacall_config.json", "w", encoding='utf-8') as fd: + datacall_config_json = ujson.dumps(datacall_config) + fd.write(datacall_config_json) + else: + # print('[Warning]The datacall_config.json file does not exist, create it now.') + default_config = { + "1": {"autoActivate": 0, "autoConnect": 0}, + "2": {"autoActivate": 0, "autoConnect": 0}, + "3": {"autoActivate": 0, "autoConnect": 0} + } + if cur_simid ==1: + default_config[str(profileID)]["autoActivate_1"] = enable + else: + default_config[str(profileID)]["autoActivate"] = enable + with open("/usr/datacall_config.json", "w", encoding='utf-8') as fd: + default_config_json = ujson.dumps(default_config) + fd.write(default_config_json) + """ + return -1 + + +def setAutoConnect(profileID, enable, cur_simid=None): + """ + if profileID < 1 or profileID > 3: + raise ValueError("invalid value, profileID should be in [1,3].") + if enable != 0 and enable != 1: + raise ValueError("invalid value, enable should be 0 or 1.") + if cur_simid != None and cur_simid != 0 and cur_simid != 1: + raise ValueError("invalid value, enable should be 0 or 1.") + + if "datacall_config.json" in uos.listdir('/usr'): + with open("/usr/datacall_config.json", "r", encoding='utf-8') as fd: + try: + datacall_config = ujson.load(fd) + if not isinstance(datacall_config, dict): + raise ValueError("The format of the datacall_config.json is incorrect.") + value_of_key_profileid = datacall_config.get(str(profileID), None) + if value_of_key_profileid is not None: + if not isinstance(value_of_key_profileid, dict): + raise ValueError("The format of the datacall_config.json is incorrect.") + if cur_simid ==1: + datacall_config[str(profileID)]["autoConnect_1"] = enable + else: + datacall_config[str(profileID)]["autoConnect"] = enable + else: + if cur_simid ==1: + datacall_config[str(profileID)] = {"autoActivate": 0, "autoConnect": 0,"autoConnect_1": enable} + else: + datacall_config[str(profileID)] = {"autoActivate": 0,"autoConnect": enable} + except Exception: + raise ValueError("The format of the datacall_config.json is incorrect.") + with open("/usr/datacall_config.json", "w", encoding='utf-8') as fd: + datacall_config_json = ujson.dumps(datacall_config) + fd.write(datacall_config_json) + else: + # print('[Warning]The datacall_config.json file does not exist, create it now.') + default_config = { + "1": {"autoActivate": 0, "autoConnect": 0}, + "2": {"autoActivate": 0, "autoConnect": 0}, + "3": {"autoActivate": 0, "autoConnect": 0} + } + if cur_simid ==1: + default_config[str(profileID)]["autoConnect_1"] = enable + else: + default_config[str(profileID)]["autoConnect"] = enable + with open("/usr/datacall_config.json", "w", encoding='utf-8') as fd: + default_config_json = ujson.dumps(default_config) + fd.write(default_config_json) + """ + if cur_simid != None: + dial.setAutoConnect(profileID, enable,cur_simid) + else: + dial.setAutoConnect(profileID, enable) + + + +def setPDPContext(profileID, ipType, apn, username, password, authType, cur_simid=None): + if profileID < 1 or profileID > 3: + raise ValueError("invalid value, profileID should be in [1,3].") + if authType < 0 or authType >3: + raise ValueError("invalid value.") + # Users can set apn, username, and password to None. + # When it is set to None, it means that the original values will not be changed and the original values will be used instead. + if apn is None or username is None or password is None: + pdp_context = dial.getPDPContext(profileID) + if not isinstance(pdp_context,tuple) or len(pdp_context) < 3: + raise ValueError("getPDPContext error.") + if apn is None: + apn = pdp_context[1] + if username is None: + username = pdp_context[2] + if password is None: + password = pdp_context[3] + # if len(username) == 0 and len(password) == 0 and authType != 0: + # authType = 0 + if (len(username) != 0 or len(password) != 0) and authType == 0: + authType = 2 + if cur_simid == None: + return dial.setPDPContext(profileID, ipType, apn, username, password, authType) + else: + return dial.setPDPContext(profileID, ipType, apn, username, password, authType, cur_simid) + + +def getPDPContext(profileID, cur_simid=None): + if profileID < 1 or profileID > 3: + raise ValueError("invalid value, profileID should be in [1,3].") + if cur_simid == None: + return dial.getPDPContext(profileID) + else: + return dial.getPDPContext(profileID, cur_simid) + + + +def setDNSServer(profileID, simID, priDNS, secDNS): + if profileID < 1 or profileID > 3: + raise ValueError("invalid value, profileID should be in [1,3].") + return dial.setDnsserver(profileID, simID, priDNS, secDNS) + + +def activate(profileID, cur_simid=None): + if profileID < 1 or profileID > 3: + raise ValueError("invalid value, profileID should be in [1,3].") + """ + if "datacall_config.json" in uos.listdir('/usr'): + with open("/usr/datacall_config.json", "r", encoding='utf-8') as fd: + try: + datacall_config = ujson.load(fd) + if not isinstance(datacall_config, dict): + raise ValueError("The format of the datacall_config.json is incorrect.") + value_of_key_profileid = datacall_config.get(str(profileID), None) + if value_of_key_profileid is not None: + if not isinstance(value_of_key_profileid, dict): + raise ValueError("The format of the datacall_config.json is incorrect.") + auto_connect = value_of_key_profileid.get("autoConnect", 0) + dial.setAutoConnect(profileID, auto_connect) + else: + raise ValueError("No configuration information for profileID {}.".format(profileID)) + except Exception: + raise ValueError("The format of the datacall_config.json is incorrect.") + """ + if cur_simid == None: + return dial.start(profileID, 0, "", "", "", 0) + else: + return dial.start(profileID, 0, "", "", "", 0,cur_simid) + + +def deactivate(profileID, cur_simid=None): + if profileID < 1 or profileID > 3: + raise ValueError("invalid value, profileID should be in [1,3].") + + pdpctx = dial.getPDPContext(profileID) + if pdpctx != -1: + iptype = pdpctx[0] + if cur_simid == None: + return dial.stop(profileID, iptype) + else: + return dial.stop(profileID, iptype,cur_simid) + else: + return -1 + +###################################################################################### + +def start(profileidx, iptype=0, apn="", username="", password="", authtype=0, cur_simid=None): + ret = dial.setPDPContext(profileidx, iptype, apn, username, password, authtype) + if ret == 0: + if cur_simid == None: + return dial.start(profileidx, iptype, apn, username, password, authtype) + else: + return dial.start(profileidx, iptype, apn, username, password, authtype, cur_simid) + else: + return -1 + + +def stop(profileidx, iptype,cur_simid=None): + if cur_simid == None: + return dial.stop(profileidx, iptype) + else: + return dial.stop(profileidx, iptype, cur_simid) + + +def getInfo(profileidx, iptype, cur_simid=None): + if cur_simid == None: + ret = dial.getInfo(profileidx, iptype) + else: + ret = dial.getInfo(profileidx, iptype, cur_simid) + if ret == -1: + ipv4 = [0, 0, '0.0.0.0', '0.0.0.0', '0.0.0.0'] + ipv6 = [0, 0, '::', '::', '::'] + if iptype ==2: + return (profileidx, iptype, ipv4, ipv6) + elif iptype == 1: + return (profileidx, iptype, ipv6) + elif iptype == 0: + return (profileidx, iptype, ipv4) + return ret + +def getAddressinfo(profileidx, iptype): + ret = dial.getAddressinfo(profileidx, iptype) + if ret == -1: + ipv4 = ['00-00-00-00-00-00', '0.0.0.0', '0.0.0.0'] + ipv6 = ['00-00-00-00-00-00', '::', '::'] + if iptype ==2: + return (ipv4, ipv6) + elif iptype == 1: + return (ipv6) + elif iptype == 0: + return (ipv4) + return ret + +def getSiminfo(simID): + ret = dial.getSiminfo(simID) + if ret == -1: + return (0, 0, 0, 0) + return ret + +def setAsynMode(mode): + return dial.setAsynMode(mode) + +def setCallback(usrfun): + return dial.setCallback(usrfun) + +def setDnsserver(profileidx, simid, new_pri, new_sec): + return dial.setDnsserver(profileidx, simid, new_pri, new_sec) + +def getSpeed(): + return dial.getSpeed() + diff --git a/ports/quectel/modules/file_crc32.py b/ports/quectel/modules/file_crc32.py new file mode 100644 index 0000000000000..7e64adc90e152 --- /dev/null +++ b/ports/quectel/modules/file_crc32.py @@ -0,0 +1,45 @@ +# Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. +# +# 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. + + +from utils import crc32 + +READ_BLOCK_SIZE = 4096 + +def _check(fp): + fp.seek(0) + fr = fp.read(READ_BLOCK_SIZE) + while fr: + yield fr + fr = fp.read(READ_BLOCK_SIZE) + else: + fp.seek(0) + +def calc(file_name): + csumFunc = crc32() + csum = 0xffffffff + flag = 0 + try: + with open(file_name, 'rb') as fp: + for fr in _check(fp): + csum = csumFunc.update(csum, fr) + flag = 1 + fp.close() + except Exception as e: + pass + finally: + if not flag: + return None + return hex(csum) + diff --git a/ports/quectel/modules/log.py b/ports/quectel/modules/log.py new file mode 100644 index 0000000000000..6a64d1fe3998e --- /dev/null +++ b/ports/quectel/modules/log.py @@ -0,0 +1,119 @@ +# Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. +# +# 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. + +import usys + +CRITICAL = 50 +ERROR = 40 +WARNING = 30 +INFO = 20 +DEBUG = 10 +NOTSET = 0 + +_level_dict = { + CRITICAL: "CRIT", + ERROR: "ERROR", + WARNING: "WARN", + INFO: "INFO", + DEBUG: "DEBUG", +} + +_stream = usys.stderr + +class LogRecord: + def __init__(self): + self.__dict__ = {} + + def __getattr__(self, key): + return self.__dict__[key] + +class Logger: + + level = NOTSET + handlers = [] + record = LogRecord() + + def __init__(self, name): + self.name = name + + def _level_str(self, level): + l = _level_dict.get(level) + if l is not None: + return l + return "LVL%s" % level + + def setLevel(self, level): + self.level = level + + def isEnabledFor(self, level): + return level >= (self.level or _level) + + def log(self, level, msg, *args): + if self.isEnabledFor(level): + level = self._level_str(level) + if args: + msg = msg % args + if self.handlers: + d = self.record.__dict__ + d["levelname"] = level + d["message"] = msg + d["name"] = self.name + for h in self.handlers: + h.emit(self.record) + else: + print(level, ":", self.name, ":", msg, sep="", file=_stream) + + def debug(self, msg, *args): + self.log(DEBUG, msg, *args) + + def info(self, msg, *args): + self.log(INFO, msg, *args) + + def warning(self, msg, *args): + self.log(WARNING, msg, *args) + + def error(self, msg, *args): + self.log(ERROR, msg, *args) + + def critical(self, msg, *args): + self.log(CRITICAL, msg, *args) + + +_level = INFO +_loggers = {} + +def getLogger(name="root"): + if name in _loggers: + return _loggers[name] + l = Logger(name) + _loggers[name] = l + return l + +def set_output(out): + global _stream + from machine import UART + if isinstance(out, UART) or out == usys.stderr or out == usys.stdout: + _stream = out + else: + raise Exception("{} must extend UART".format(out)) + +def basicConfig(level=INFO, filename=None, stream=None, format=None): + global _level, _stream + _level = level + if stream: + _stream = stream + if filename is not None: + print("logging.basicConfig: filename arg is not supported") + if format is not None: + print("logging.basicConfig: format arg is not supported") \ No newline at end of file diff --git a/ports/quectel/modules/ql_fs.py b/ports/quectel/modules/ql_fs.py new file mode 100644 index 0000000000000..924cc242fd710 --- /dev/null +++ b/ports/quectel/modules/ql_fs.py @@ -0,0 +1,137 @@ +# Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. +# +# 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. + +#!python3 +# -*- coding:utf-8 -*- + +import uos +import ujson + + +class FileNotFoundError(Exception): + def __init__(self, value): + self.value = value + + def __str__(self): + return repr(self.value) + + +def path_exists(path): + if not path: + return False + else: + try: + if uos.stat(path): + return True + else: + return False + except Exception as e: + return False + + +def file_copy(dstFile, srcFile): + if not path_exists(srcFile): + return False + + dstFp = open(dstFile, 'wb+') + srcFp = open(srcFile, 'rb') + srcFr = srcFp.read(4096) + while srcFr: + dstFp.write(srcFr) + srcFr = srcFp.read(4096) + dstFp.close() + srcFp.close() + return True + + +def path_dirname(path): + if not path: + return '' + + pos = path.rfind('/') + if pos < 0: + return '' + if pos == 0: + return '/' + + dirname = '' + for i in range(0, len(path)): + if i == pos: + break + dirname = dirname + path[i] + return dirname + + +def path_getsize(path): + if path_exists(path): + return uos.stat(path)[-4] + else: + raise FileNotFoundError("can not find: '%s'" % path) + + +def mkdirs(dir): + dir_level_list = dir.split('/') + dir_step_up = dir_level_list[0] + for index in enumerate(dir_level_list): + if dir_step_up and (not path_exists(dir_step_up)): + uos.mkdir(dir_step_up) + if index[0] == (len(dir_level_list) - 1): + break + dir_step_up = dir_step_up + '/' + dir_level_list[index[0] + 1] + + +def rmdirs(dir): + ls = uos.listdir(dir) + if not ls: + uos.remove(dir) + else: + for item in ls: + item = dir + '/' + item + if int(uos.stat(item)[0]) & 0x4000: + rmdirs(item) + else: + uos.remove(item) + rmdirs(dir) + + +def touch(file, data, i=1, file_type="json"): + i = file.find("/", i) + if i != -1: + if not path_exists(file[:i]): + uos.mkdir(file[:i]) + return touch(file, data, i=i + 1, file_type=file_type) + else: + try: + with open(file, "w") as f: + if file_type == "json": + f.write(ujson.dumps(data)) + else: + f.write(data) + except Exception as e: + return -1 + else: + return 0 + + +def write_json(file, data): + return touch(file, data) + + +def read_json(file): + if path_exists(file): + with open(file, "r") as f: + return ujson.load(f) + else: + return None + diff --git a/ports/quectel/modules/queue.py b/ports/quectel/modules/queue.py new file mode 100644 index 0000000000000..223bd2e522064 --- /dev/null +++ b/ports/quectel/modules/queue.py @@ -0,0 +1,51 @@ +import _thread + + +class Queue(object): + def __init__(self, maxsize=100): + self.maxsize = maxsize + self.__deque = [] + self.__lock_queue = _thread.allocate_lock() + self.__lock_signal = _thread.allocate_lock() + self.__lock_signal.acquire() + + def put(self, item=None): + self.__lock_queue.acquire() + status = self.__put(item) + self.__lock_queue.release() + if self.__lock_signal.locked(): + self.__lock_signal.release() + return status + + def __pop(self): + self.__lock_queue.acquire() + try: + status = self.__deque.pop(0) + except Exception: + return 0, None + else: + return 1, status + finally: + self.__lock_queue.release() + + def get(self): + if not self.size(): + self.__lock_signal.acquire() + flag, status = self.__pop() + if not flag: + return self.get() + return status + + def __put(self, item): + if self.size() > self.maxsize: + return False + else: + self.__deque.append(item) + return True + + def empty(self): + return not self.size() + + def size(self): + return len(self.__deque) + diff --git a/ports/quectel/modules/request.py b/ports/quectel/modules/request.py new file mode 100644 index 0000000000000..208e3c9fbd83a --- /dev/null +++ b/ports/quectel/modules/request.py @@ -0,0 +1,470 @@ +# Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. +# +# 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. + +import usocket +import ujson +import utime +import uio + +import uos +name, platform = uos.uname()[1].split("=",1) + +if platform != "FCM360W" and platform != "FCM362K": + import net + import dataCall + + +def parse_chunked_data(sock): + data = b'' + while True: + chunk_size_str = b'' + while True: + char = sock.read(1) + if char == b'\r': + continue + if char == b'\n': + break + chunk_size_str += char + chunk_size = int(chunk_size_str, 16) + if chunk_size == 0: + break + chunk_data = sock.read(chunk_size) + data += chunk_data + sock.read(2) # discard \r\n + return data + +class Response: + def __init__(self, f, decode=True, sizeof=4096, flag=False): + self.raw = f + self.encoding = "utf-8" + self.decode = decode + self.sizeof = sizeof + self.read_len = 0 + self.read_data = sizeof + self.flag = flag + + def close(self): + if self.raw: + if s_isopen: + self.raw.close() + self.raw = None + if s_isopen: + if self.raw: + self.raw.close() + + @property + def content(self): + global s_isopen + try: + while True: + if self.read_data > 2048: + block = self.raw.read(2048) + self.read_data -= 2048 + else: + block = self.raw.read(self.read_data) + self.read_len += len(block) + if block: + yield block.decode() if self.decode else block + else: + self.raw.close() + s_isopen = False + break + if (self.flag == True) and (self.sizeof == self.read_len): + self.raw.close() + s_isopen = False + break + except Exception as e: + self.raw.close() # 2021-05-27 + s_isopen = False + if "ETIMEDOUT" in str(e): + raise ValueError(str(e)) + else: + pass + return "" + + @property + def text(self): + for i in self.content: + yield str(i) + return "" + + def json(self): + try: + json_str = "" + for i in self.content: + json_str += i + if json_str: + return ujson.loads(json_str) + else: + return None + except Exception as e: + raise ValueError( + "The data for the response cannot be converted to JSON-type data,please try use response.content method") + + +def request(method, url, data=None, json=None, files=None, stream=None, decode=True, sizeof=2048, timeout=20, headers=None, + ssl_params=None, version=0, files_data=None,files_data_len=None,files_name=None, ipvtype=0,username=None,password=None): + global port + global s_isopen + s_isopen = True + port_exist = False + addr = None + URL = url + if ipvtype == 1 and (url.split("[")[0] == "http://" or url.split("[")[0] == "https://"): + try: + proto, dummy, hosts, path = url.split("/", 3) + except ValueError: + proto, dummy, hosts = url.split("/", 2) + path = "" + + left = hosts.find('[') + if left < 0: + raise ValueError("http missing left delimiter:" + url) + + right = hosts.find(']', left + 1) + if right < 0: + raise ValueError("http missing right delimiter:" + url) + + host = hosts[left + 1:right] + + try: + if hosts[right + 1] == ':': + port = int(hosts[right + 2:]) + port_exist = True + except Exception as e: + pass + + if proto == "http:": + if not port_exist: + port = 80 + elif proto == "https:": + if not port_exist: + port = 443 + else: + raise ValueError("Unsupported protocol: " + proto) + + try: + ai = usocket.getaddrinfo(host, port, 0, usocket.SOCK_STREAM) + except Exception as e: + raise IndexError("Domain name resolution error, please check network connection:" + host) + + import uos + name, platform = uos.uname()[1].split("=",1) + if platform == "FCM360W" or platform == "FCM362K": + raise ValueError("platform Not Support IPV6!") + for i in ai: + if i[0] == 10: + addr = i[-1] + break + host = hosts + + if addr is None: + raise ValueError("Request DNS Parsing IPV6 Fail") + elif not url.split(".")[0].isdigit(): + if not url.startswith("http"): + url = "http://" + url + try: + proto, dummy, host, path = url.split("/", 3) + except ValueError: + proto, dummy, host = url.split("/", 2) + path = "" + if ":" in host: + url_info = host.split(":") + host = url_info[0] + port = int(url_info[1]) + port_exist = True + # jian.yao 2020-12-09 + if proto == "http:": + if not port_exist: + port = 80 + # jian.yao 2020-12-09 + elif proto == "https:": + if not port_exist: + port = 443 + else: + raise ValueError("Unsupported protocol: " + proto) + + try: + ai = usocket.getaddrinfo(host, port, 0, usocket.SOCK_STREAM) + except Exception as e: + raise IndexError("Domain name resolution error, please check network connection") + + if ipvtype == 1: + import uos + name, platform = uos.uname()[1].split("=",1) + if platform == "FCM360W" or platform == "FCM362K": + raise ValueError("platform Not Support IPV6!") + for i in ai: + if i[0] == 10: + addr = i[-1] + break + if addr is None: + raise ValueError("Request DNS Parsing IPV_6 Fail") + else: + for i in ai: + if i[0] == 2: + addr = i[-1] + break + if addr is None: + raise ValueError("Request DNS Parsing IPV_4 Fail") + elif url.split(".")[0].isdigit() and ":" not in url: + raise ValueError( + "MissingSchema: Invalid URL '{}': No schema supplied. Perhaps you meant http://{}? ".format(url, url)) + else: + path = "" + proto = "" + if ":" not in url: + raise ValueError("URL address error: !" + url) + try: + if "/" in url: + ip_info = url.split('/', 1) + path = ip_info[1] + host, port = ip_info[0].split(":") + else: + host, port = url.split(":") + except: + raise ValueError("URL address error: " + url) + try: + ai = usocket.getaddrinfo(host, port, 0, usocket.SOCK_STREAM) + except Exception as e: + raise IndexError("Domain name resolution error, please check network connection") + + if ipvtype == 1: + import uos + name, platform = uos.uname()[1].split("=",1) + if platform == "FCM360W" or platform == "FCM362K": + raise ValueError("platform Not Support IPV6!") + for i in ai: + if i[0] == 10: + addr = i[-1] + break + if addr is None: + raise ValueError("Request DNS Parsing IPV6 Fail") + else: + for i in ai: + if i[0] == 2: + addr = i[-1] + break + if addr is None: + raise ValueError("Request DNS Parsing IPV4 Fail") + #global s + + if ipvtype == 1: + import uos + name, platform = uos.uname()[1].split("=",1) + if platform == "FCM360W" or platform == "FCM362K": + raise ValueError("platform Not Support IPV6!") + try: + s = usocket.socket(usocket.AF_INET6, usocket.SOCK_STREAM, usocket.TCP_CUSTOMIZE_PORT) + except Exception as e: + raise RuntimeError("socket resource malloc FAIL='{}'".format(str(e))) + call_state = dataCall.getInfo(1,1) + if call_state == -1: + raise ValueError("request Connect dataCall get Info FAIL") + elif call_state[2][0] != 1: + raise ValueError("request Connect dataCall get IPV6 Info FAIL") + try: + s.bind((call_state[2][2],0)) + except Exception as e: + raise ValueError("request sock bind IPV6 IP FAIL") + else: + try: + s = usocket.socket(usocket.AF_INET, usocket.SOCK_STREAM) + except Exception as e: + raise RuntimeError("socket resource malloc FAIL='{}'".format(str(e))) + + s.settimeout(timeout) + try: + try: + s.connect(addr) + except Exception as e: + s.close() + raise RuntimeError("HTTP Connection '{}' FAIL='{}'".format(str(e), URL)) + if proto == "https:": + import ussl + try: + if ssl_params: + s = ussl.wrap_socket(s, **ssl_params, server_hostname=host) + else: + s = ussl.wrap_socket(s, server_hostname=host) + except Exception as e: + s.close() + raise RuntimeError("HTTPS USSL '{}' FAIL='{}'".format(str(e), URL)) + if version == 1: + s.write(b"%s /%s HTTP/1.1\r\n" % (method, path)) + else: + s.write(b"%s /%s HTTP/1.0\r\n" % (method, path)) + s.write(b"Host: %s\r\n" % host) + if version == 1: + s.write(b"Connection: close\r\n") + if headers: + if files: + boundary = str(utime.time()) + if not (files.get("filepath") and files.get("filename")): + raise ValueError("Missing key parameters 'filepath' and 'filename'") + if headers.get('Content-Type') == "multipart/form-data": + headers['Content-Type'] = headers['Content-Type'] + '; boundary={}'.format(boundary) + headers['charset'] = 'UTF-8' + if files_data: + boundary = str(utime.time()) + if headers.get('Content-Type') == "multipart/form-data": + headers['Content-Type'] = headers['Content-Type'] + '; boundary={}'.format(boundary) + headers['charset'] = 'UTF-8' + else: + headers = dict() + if files: + boundary = str(utime.time()) + headers['Content-Type'] = "multipart/form-data; boundary={}".format(boundary) + headers['charset'] = 'UTF-8' + if json: + headers['Content-Type'] = "application/json" + for k in headers: + s.write(k) + s.write(b": ") + s.write(headers[k]) + s.write(b"\r\n") + if (username is not None) and (password is not None): + try: + import ubinascii + key = "{}:{}".format(username, password) + key_64 = ubinascii.b2a_base64(key)[:-1].decode('utf-8') + s.write(b"Authorization: Basic {}\r\n".format(key_64)) + except Exception as e: + s.close() + raise RuntimeError("HTTP base64 FAIL='{}'".format(str(e))) + if json is not None: + assert data is None + data = ujson.dumps(json) + if data: + s.write(b"Content-Length: %d\r\n" % len(data)) + s.write(b"\r\n") + s.write(data) + if files_data: + if files_name == None: + raise ValueError("files_name must have") + if files_data_len == None: + raise ValueError("files_data_len must have") + import uos + name,platform = uos .uname()[1].split("=",1) + datas = '--{0}{1}Content-Disposition: form-data; name="file"; filename="{2}"{1}Content-Type: application/octet-stream{1}{1}'.format( + boundary, '\r\n', files_name) + suffix = '{1}--{0}--{1}'.format(boundary, '\r\n') + len_d = files_data_len + len(datas) + len(suffix) + s.write(b"Content-Length: %d\r\n" % len_d) + s.write(b"\r\n") + s.write(datas) + s.write(files_data[0:files_data_len]) + s.write(suffix) + if files: + import uos + counter = 0 + name,platform = uos .uname()[1].split("=",1) + file_path = files.get("filepath") + with open(file_path, 'rb') as f: + content = f.read(4096) + if files.get("name") is not None: + datas = '--{0}{1}Content-Disposition: form-data; {2}{1}{1}{3}{1}--{0}'. \ + format(boundary, '\r\n', files.get("name"), content) + else: + datas = '--{0}{1}Content-Disposition: form-data; name="file"; filename="{2}"{1}Content-Type: application/octet-stream{1}{1}'.format( + boundary, '\r\n', files.get("filename")) + if files.get("filepath1") is not None: + with open('{}'.format(files.get("filepath1")), 'r') as f1: + content1 = f1.read() + if files.get("name1") is not None: + datas += '{1}Content-Disposition: form-data; {2}{1}{1}{3}{1}--{0}'. \ + format(boundary, '\r\n', files.get("name1"), content1) + else: + if files.get("filename1") is None: + raise ValueError("Missing key parameters 'filename1' ") + datas += '{1}Content-Disposition: form-data; name="file"; filename="{2}"{1}Content-Type: application/octet-stream{1}{1}{3}{1}--{0}'. \ + format(boundary, '\r\n', files.get("filename1"), content1) + suffix = '{1}--{0}--{1}'.format(boundary, '\r\n') + len_d = uos.stat(file_path)[-4] + len(datas) + len(suffix) + s.write(b"Content-Length: %d\r\n" % len_d) + s.write(b"\r\n") + s.write(datas) + while content: + s.write(content) + content = f.read(4096) + s.write(suffix) + if not (files and data and files_data): + s.write(b"\r\n") + l = s.readline() + uheaders = {} + chunked_encoding = False + try: + # jian.yao 2020-12-09 Abnormal response handle + l = l.split(None, 2) + status = int(l[1]) + except: + raise ValueError("InvalidSchema: No connection adapters were found for '{}'".format(URL)) + reason = "" + if len(l) > 2: + reason = l[2].rstrip() + con_len = sizeof + con_flag = False + while True: + l = s.readline() + j = l.decode().split(":") + try: + uheaders[j[0]] = j[1].replace("\n", "").replace("\r", "") + except Exception as e: + pass + if not l or l == b"\r\n": + break + + if l.lower().startswith(b"transfer-encoding:"): + if b"chunked" in l.lower(): + chunked_encoding = True + if l.startswith(b'Content-Length:'): + con_len = int(l.split(b' ')[1]) + con_flag = True + #if l.startswith(b"Location:") and not 200 <= status <= 299: + #raise NotImplementedError("Redirects not yet supported") + except OSError: + s.close() + raise + if chunked_encoding: + resp = Response(uio.BytesIO(parse_chunked_data(s)), sizeof=con_len) + else: + resp = Response(s,sizeof=con_len, flag=con_flag) + resp.status_code = status + resp.reason = reason + resp.headers = uheaders + return resp + + +def head(url, **kw): + return request("HEAD", url, **kw) + + +def get(url, **kw): + return request("GET", url, **kw) + + +def post(url, **kw): + return request("POST", url, **kw) + + +def put(url, **kw): + return request("PUT", url, **kw) + + +def patch(url, **kw): + return request("PATCH", url, **kw) + + +def delete(url, **kw): + return request("DELETE", url, **kw) diff --git a/ports/quectel/modules/umqtt.py b/ports/quectel/modules/umqtt.py new file mode 100644 index 0000000000000..6daa88dbc133e --- /dev/null +++ b/ports/quectel/modules/umqtt.py @@ -0,0 +1,776 @@ +# Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. +# +# 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. + + +import uos +name, platform = uos.uname()[1].split("=",1) + +import utime +import log +import _thread +import usocket as socket +import ustruct as struct +import osTimer + +if platform != "FCM360W" and platform != "FCM362K": + import net + import dataCall + +log.basicConfig(level=log.INFO) +mqtt_log = log.getLogger("MQTT") +# bob.xian 2023/9/20 [FCM360W may be a bit unstable when using the log module, so print is temporarily used] begin +if platform == "FCM360W": + mqtt_log.info = print + mqtt_log.warning = print +# bob.xian 2023/9/20 [FCM360W may be a bit unstable when using the log module, so print is temporarily used] end + +#ALIYDEVREGISTER = False +#TOPICLIST = list() +#SERVERACK = set() # PUBACK and SUBACK pids awaiting ACK response +#PING = False + +class MQTTException(Exception): + pass + +def pid_gen(): + pid = 0 + while True: + pid = pid + 1 if pid < 65535 else 1 + yield pid + +class BaseMqtt(object): + CONNECTEXCE = -1 + CONNECTSUCCESS = 0 + ARECONNECT = 1 + SEVCLOSE = 2 + + def __init__(self, client_id, server, port=0, user=None, password=None, keepalive=0, + ssl=False, ssl_params={}, reconn=True, version=4, pingmaxnum=0, manage=False, ipvtype=0): + if port == 0: + port = 8883 if ssl else 1883 + self.client_id = client_id + self.sock = None + self.server = server + self.port = port + self.ssl = ssl + self.ssl_params = ssl_params + self.pid = 0 + self.__newpid = pid_gen() + self.__rcv_pids = set() # PUBACK and SUBACK pids awaiting ACK response + self.cb = None + self.user = user + self.pswd = password + self.keepalive = keepalive + self.lw_topic = None + self.lw_msg = None + self.lw_qos = 0 + self.lw_retain = False + self.last_time = None + self.timerFlag = True + self.pingFlag = False + self.connSta = False + self.reconn = reconn + self.topic_list = [] + self.addr = None + self.qos = 0 + self.mqttversion = version + self.clean_session = True + self.ping_outstanding = False + self.pingmaxnum = pingmaxnum + self.pingnum = 0 + self.mqttlock = None + self.mqttsendlock = None + self.mqttmsglock = None + self.threadId = None + self.__response_time = 5000 + self.wait_flag = 0 + self.ipvtype = ipvtype + self.manage = manage + self.looptask_id = None + self.PING = False + self.SERVERACK = set() # PUBACK and SUBACK pids awaiting ACK response + self.TOPICLIST = list() + self.ALIYDEVREGISTER = False + if keepalive != 0 and keepalive < 5: + raise ValueError("inport parameter error : keepalive >= 5S") + + def _send_str(self, s): + self.sock.write(struct.pack("!H", len(s))) + self.sock.write(s) + + def _recv_len(self): + n = 0 + sh = 0 + while 1: + b = self.sock.read(1)[0] + n |= (b & 0x7f) << sh + if not b & 0x80: + return n + sh += 7 + + def set_callback(self, f): + self.cb = f + + def set_last_will(self, topic, msg, retain=False, qos=0): + assert 0 <= qos <= 2 + assert topic + self.lw_topic = topic + self.lw_msg = msg + self.lw_qos = qos + self.lw_retain = retain + + def connect(self, clean_session=True): + if self.mqttlock is None: + self.mqttlock = _thread.allocate_lock() + if self.mqttsendlock is None: + self.mqttsendlock = _thread.allocate_lock() + if self.mqttmsglock is None: + self.mqttmsglock = _thread.allocate_lock() + j = 1 + while True: + if j > 5: + raise ValueError("DNS Parsing NULL") + try: + addrall = socket.getaddrinfo(self.server, self.port) + except Exception as e: + raise ValueError("DNS Parsing '{}'".format(self.server)) + if not addrall: + j += 1 + utime.sleep_ms(500) + continue + if self.ipvtype == 1: + for i in addrall: + if i[0] == 10: + self.addr = i[-1] + break + if self.addr is None: + raise ValueError("DNS Parsing IPV6 Fail") + else: + try: + self.addr = addrall[0][-1] + except Exception as e: + raise ValueError("DNS Parsing IPV4 Fail") + break + + if self.ipvtype == 1: + if platform == "FCM360W" or platform == "FCM362K": + print("Not Support!") + return + self.sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM, socket.TCP_CUSTOMIZE_PORT) + call_state = dataCall.getInfo(1,1) + if call_state == -1: + raise ValueError("MQTT Connect dataCall get Info FAIL") + elif call_state[2][0] != 1: + raise ValueError("MQTT Connect dataCall get IPV6 Info FAIL") + try: + self.sock.bind((call_state[2][2],0)) + except Exception as e: + raise ValueError("sock bind IPV6 IP FAIL") + else: + self.sock = socket.socket() + self.sock.settimeout(20) + self.sock.connect(self.addr) + if self.ssl: + import ussl + self.sock = ussl.wrap_socket(self.sock, **self.ssl_params, server_hostname = self.server) + + if self.mqttversion == 3: + protocol = b"MQIsdp" + else: + protocol = b"MQTT" + + connect_flags = 0 + connect_flags = clean_session << 1 + remaining_length = 2 + len(protocol) + 1 + 1 + 2 + + if self.client_id: + remaining_length = remaining_length + 2 + len(self.client_id) + if self.user: + remaining_length = remaining_length + 2 + len(self.user) + connect_flags = connect_flags | 0x80 + if self.pswd: + connect_flags = connect_flags | 0x40 + remaining_length = remaining_length + 2 + len(self.pswd) + if self.lw_topic: + connect_flags = connect_flags | 0x04 | ((self.lw_qos & 0x03) << 3) | ((self.lw_retain & 0x01) << 5) + remaining_length += 2 + len(self.lw_topic) + 2 + len(self.lw_msg) + + command = 0x10 + packet = bytearray() + packet.extend(struct.pack("!B", command)) + remaining_bytes = [] + while True: + byte = remaining_length % 128 + remaining_length = remaining_length // 128 + if remaining_length > 0: + byte = byte | 0x80 + + remaining_bytes.append(byte) + packet.extend(struct.pack("!B", byte)) + if remaining_length == 0: + break + + if self.mqttversion == 3: + packet.extend(struct.pack("!H" + str(len(protocol)) + "sBBH", len(protocol), protocol, 3, connect_flags, + self.keepalive)) + else: + packet.extend(struct.pack("!H" + str(len(protocol)) + "sBBH", len(protocol), protocol, 4, connect_flags, + self.keepalive)) + if self.client_id: + packet.extend(struct.pack("!H" + str(len(self.client_id)) + "s", len(self.client_id), self.client_id)) + if self.lw_topic: + packet.extend(struct.pack("!H" + str(len(self.lw_topic)) + "s", len(self.lw_topic), self.lw_topic)) + packet.extend(struct.pack("!H" + str(len(self.lw_msg)) + "s", len(self.lw_msg), self.lw_msg)) + if self.user: + packet.extend(struct.pack("!H" + str(len(self.user)) + "s", len(self.user), self.user)) + if self.pswd: + packet.extend(struct.pack("!H" + str(len(self.pswd)) + "s", len(self.pswd), self.pswd)) + + self.sock.write(packet) + + resp = self.sock.read(4) + self.sock.setblocking(True) + assert resp[0] == 0x20 and resp[1] == 0x02 + if resp[3] != 0: + raise MQTTException(resp[3]) + # self.last_time = utime.mktime(utime.localtime()) + self.last_time = utime.ticks_ms() // 1000 + self.connSta = True + self.clean_session = clean_session + self.PING = False + self.pingnum = self.pingmaxnum + self.ALIYDEVREGISTER = self.sock + return resp[2] & 1 + + def disconnect(self): + # Pawn.zhou 2021/1/12 for JIRA STASR3601-2523 begin + try: + self.timerFlag = False + self.pingFlag = False + self.connSta = False + self.PING = False + self.pingnum = self.pingmaxnum + self.topic = [] + self.sock.write(b"\xe0\0") + # Pawn.zhou 2021/1/12 for JIRA STASR3601-2523 end + except: + mqtt_log.warning("Error send mqtt_dis FAIL.") + try: + if self.mqttsendlock.locked(): + self.mqttsendlock.release() + if self.mqttlock.locked(): + self.mqttlock.release() + if self.mqttmsglock.locked(): + self.mqttmsglock.release() + if self.mqttlock is not None: + _thread.delete_lock(self.mqttlock) + self.mqttlock = None + if self.mqttsendlock is not None: + _thread.delete_lock(self.mqttsendlock) + self.mqttsendlock = None + if self.mqttmsglock is not None: + _thread.delete_lock(self.mqttmsglock) + self.mqttmsglock = None + except: + mqtt_log.warning("Error delete_lock FAIL.") + utime.sleep_ms(500) + try: + self.sock.close() + except: + mqtt_log.warning("Error socket close FAIL.") + + def close(self): + self.sock.close() + + def ping(self): + # self.last_time = utime.mktime(utime.localtime()) + self.last_time = utime.ticks_ms() // 1000 + self.sock.write(b"\xc0\0") + self.PING = True + + def publish(self, topic, msg, retain=False, qos=0): + pkt = bytearray(b"\x30\0\0\0") + pid = next(self.__newpid) + pkt[0] |= qos << 1 | retain + sz = 2 + len(topic) + len(msg) + if qos > 0: + sz += 2 + assert sz < 2097152 + i = 1 + while sz > 0x7f: + pkt[i] = (sz & 0x7f) | 0x80 + sz >>= 7 + i += 1 + pkt[i] = sz + self.sock.write(pkt, i + 1) + self._send_str(topic) + if qos > 0: + self.SERVERACK.add(pid) + struct.pack_into("!H", pkt, 0, pid) + self.sock.write(pkt, 2) + self.sock.write(msg) + # self.last_time = utime.mktime(utime.localtime()) + if qos == 0: + if self.keepalive >= 30: + # time = utime.mktime(utime.localtime()) + time = utime.ticks_ms() // 1000 + if (time - self.last_time) > (self.keepalive - 15): + self.last_time = time - self.keepalive + return True + + if qos == 1: + if self.wait_flag == 0: + self.wait_msg() + if not self._await_pid(pid): + mqtt_log.warning("publish Pid[%s] QOS1 message was not received correctly"%pid) + return False + else: + # self.last_time = utime.mktime(utime.localtime()) + self.last_time = utime.ticks_ms() // 1000 + return True + elif qos == 2: + mqtt_log.warning("publish QOS2 Not Support") + assert 0 + + def __subscribe(self, topic, qos, sock): + if sock: + self.sock = sock + pkt = bytearray(b"\x82\0\0\0") + pid = next(self.__newpid) + self.SERVERACK.add(pid) + struct.pack_into("!BH", pkt, 1, 2 + 2 + len(topic) + 1, pid) + self.sock.write(pkt) + self._send_str(topic) + self.sock.write(qos.to_bytes(1, "little")) + if self.ssl == False: + self.sock.settimeout(5) + while True: + if self.wait_flag == 0: + if self.mqttmsglock.locked(): + return True + op = self.wait_msg() + if op == 0x90: + return True + else: + return False + else: + if not self._await_pid(pid): + return False + else: + return True + + def subscribe(self, topic, qos=0, sock=None): + assert self.cb is not None, "Subscribe callback is not set" + if topic not in self.topic_list: + self.topic_list.append(topic) + self.TOPICLIST = self.topic_list + self.qos = qos + self.__subscribe(topic, qos=qos, sock=sock) + + def publish_ack(self, pid): + pkt = bytearray(b"\x40\x02\0\0") + struct.pack_into("!H", pkt, 2, pid) + while True: + try: + if self.mqttsendlock.locked(): + utime.sleep_ms(10) + continue + self.mqttsendlock.acquire() + self.sock.write(pkt) + self.mqttsendlock.release() + return + except Exception as e: + mqtt_log.warning("Publish Pid[%s] ACK OSError[%s]." %(pid, str(e))) + if self.mqttsendlock.locked(): + self.mqttsendlock.release() + return + + # Wait for a single incoming MQTT message and process it. + # Subscribed messages are delivered to a callback previously + # set by .set_callback() method. Other (internal) MQTT + # messages processed internally. + def wait_msg(self): + global SUBACK + SUBACK = True + if self.ssl: + res = self.sock.read(1) + else: + res = self.sock.recv(1) + self.sock.setblocking(True) + if res is None: + return None + if res == b"": + # raise OSError(-1) + # Pawn 2020/11/14 - WFZT mqttBUg -1 + return None + + if res == b"\xd0": # PINGRESP + self.PING = False + sz = self.sock.read(1)[0] + assert sz == 0 + return res + + if res == b'\x40': # PUBACK: save pid + sz = self.sock.read(1) + if sz != b"\x02": + mqtt_log.warning("Publish message does not return ACK correctly") + return + rcv_pid = self.sock.read(2) + pid = rcv_pid[0] << 8 | rcv_pid[1] + if pid in self.SERVERACK: + self.SERVERACK.discard(pid) + return + else: + return + + sub_ack = res[0] + if (sub_ack & 0xf0) == 0x90: # SUBSCRIBE: + resp = self.sock.read(4) + pid = resp[1] << 8 | resp[2] + if pid in self.SERVERACK: + self.SERVERACK.discard(pid) + if resp[3] == 0x80: + mqtt_log.warning("subscribe topic ACK Fail") + return 0x80 + else: + return 0x90 + + op = res[0] + if op & 0xf0 != 0x30: + return op + sz = self._recv_len() + topic_len = self.sock.read(2) + topic_len = (topic_len[0] << 8) | topic_len[1] + topic = self.sock.read(topic_len) + sz -= topic_len + 2 + if op & 6: + pid = self.sock.read(2) + pid = pid[0] << 8 | pid[1] + sz -= 2 + msg = self.sock.read(sz) + # self.last_time = utime.mktime(utime.localtime()) + if op & 6 == 2: + task_stacksize = _thread.stack_size() + name,platform = uos.uname()[1].split("=",1) + if platform == "EC600E" or platform == "EC800E" or platform == "FCM360W" or platform == "FCM362K": + _thread.stack_size(2*1024) + _thread.start_new_thread(self.publish_ack, (pid,)) + _thread.stack_size(task_stacksize) + if op & 6 == 4: + assert 0 + try: + self.cb(topic, msg) + except Exception as e: + mqtt_log.warning("set_callback OSError[%s]." % str(e)) + + # Checks whether a pending message from server is available. + # If not, returns immediately with None. Otherwise, does + # the same processing as wait_msg. + def check_msg(self): + self.sock.setblocking(False) + return self.wait_msg() + + def _timeout(self, t): + return utime.ticks_diff(utime.ticks_ms(), t) > self.__response_time + + def _await_pid(self, pid): + t = utime.ticks_ms() + while pid in self.SERVERACK: # local copy + if self._timeout(t): + break # Must repub or bail out + utime.sleep_ms(500) + else: + return True # PID received. All done. + return False + + def get_mqttsta(self): + ''' + Get the MQTT connection status + CONNECTEXCE -1:Connect the interrupt + CONNECTSUCCESS 0:connection is successful + ARECONNECT 1:In the connection + SEVCLOSE 2:server closes the connection + ''' + socket_sta = self.sock.getsocketsta() + if socket_sta == 0: + return self.ARECONNECT + elif (socket_sta == 2) or (socket_sta == 3): + return self.ARECONNECT + elif (socket_sta == 4) and self.connSta: + return self.CONNECTSUCCESS + elif (socket_sta == 7) or (socket_sta == 8): + return self.SEVCLOSE + else: + return self.CONNECTEXCE + + +class MQTTClient(BaseMqtt): + DELAY = 2 + DEBUG = False + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.error_callback = None + self.subtimer = osTimer() + + def delay(self, i): + utime.sleep(self.DELAY) + + def disconnect(self): + try: + self.subtimer.stop() + self.subtimer.delete_timer() + except: + pass + super().disconnect() + + def sub_timer_task(self, arg): + if not self.topic_list: + self.topic_list = self.TOPICLIST + for topic_re in self.topic_list: + super().subscribe(topic_re, qos=self.qos, sock=self.ALIYDEVREGISTER) + + def error_register_cb(self, func): + self.error_callback = func + + def base_reconnect(self): + i = 0 + if self.mqttlock.locked(): + return + self.mqttlock.acquire() + if self.looptask_id is not None and self.PING != True: + if self.mqttsendlock.locked(): + self.mqttsendlock.release() + if self.wait_flag == 0: + _thread.stop_thread(self.looptask_id) + self.looptask_id = None + if self.reconn: + if self.error_callback is not None: + e = "reconnect_start" + self.error_callback(e)#start reconnect + while 1: + try: + if not self.timerFlag: + break + #felix.hou 2024.5.11 add ,close() may cause reconnecting to the mqtt server to fail + if platform == "FCM360W" or platform == "FCM362K": + self.sock.shutdown() + utime.sleep_ms(20) + self.sock.close() + else: + self.sock.close() + #felix.hou 2024.5.11 add ,close() may cause reconnecting to the mqtt server to fail + time_info = self.logTime() + mqtt_log.info( + "[%s] The network condition has been restored and an attempt will be made to reconnect" % time_info) + self.pingFlag = False + self.connSta = False + self.connect(self.clean_session) + mqtt_log.info("[%s] Reconnection successful!" % time_info) + if self.manage: + self.subtimer.start(3000, 0, self.sub_timer_task) + else: + if not self.topic_list: + self.topic_list = self.TOPICLIST + for topic_re in self.topic_list: + super().subscribe(topic_re, self.qos) + time_info = self.logTime() + if self.mqttlock.locked(): + self.mqttlock.release() + if self.reconn: + if self.error_callback is not None: + e = "reconnect_success" + try: + self.error_callback(e)#reconnect success + except Exception as e: + mqtt_log.warning("error_callback OSError[%s]." % str(e)) + return + except Exception as e: + if not self.timerFlag: + break + i += 1 + time_info = self.logTime() + mqtt_log.warning( + "[%s] The connection attempt failed [%s] and will be tried again after %d seconds." % (time_info, str(e), 5 + i)) + utime.sleep(5 + i) + if platform != "FCM360W" and platform != "FCM362K": + net_sta = net.getState() + if net_sta != -1 and ((net_sta[1][0] == 1) or (net_sta[1][0] == 5)): + call_state = dataCall.getInfo(1, 0) + if call_state == -1: + mqtt_log.info("LTE datacall Fail.") + elif call_state[2][0] != 1: + mqtt_log.info("LTE datacall IPV4 Fail.") + else: + mqtt_log.info("LTE Net unregistered.") + + def publish(self, topic, msg, retain=False, qos=0): + while True: + try: + if self.mqttsendlock.locked(): + utime.sleep_ms(10) + continue + self.mqttsendlock.acquire() + ret = super().publish(topic, msg, retain, qos) + self.mqttsendlock.release() + return ret + except Exception as e: + mqtt_log.warning("Publish Fail OSError[%s]." % str(e)) + if self.mqttsendlock.locked(): + self.mqttsendlock.release() + return False + + def wait_msg(self): + while True: + try: + # The state changes when disconnect is called + if not self.timerFlag: + break + self.wait_flag = 1 + if self.mqttmsglock.locked(): + utime.sleep_ms(10) + continue + self.mqttmsglock.acquire() + ret = super().wait_msg() + self.mqttmsglock.release() + self.wait_flag = 0 + return ret + except Exception as e: + if self.mqttmsglock is not None and self.mqttmsglock.locked(): + self.mqttmsglock.release() + if not self.timerFlag: + break + if not self.reconn: + raise e + # Whether to use the built-in reconnect mechanism + time_info = self.logTime() + self.wait_flag = 0 + if self.ping == True: + mqtt_log.warning("[%s] wait msg, send ping timeout. Trying to reconnect" % time_info) + else: + mqtt_log.warning("[%s] wait msg OSError[%s] . Trying to reconnect" % (time_info, str(e))) + utime.sleep(1) + self.base_reconnect() + + def connect(self, clean_session=True): + try: + super().connect(clean_session) + except Exception as e: + if str(e) == "104": + raise ValueError( + "MQTT Connect Error='{}' Server Actively RST Disconnected.Need Check addr&port".format(e)) + elif str(e) == "107" or str(e) == "4": + raise ValueError( + "MQTT Connect Error='{}' Server Actively FIN Disconnected.Need Check Connection parameters".format( + e)) + elif str(e) == "110": + raise ValueError("MQTT Connect Error='{}' Timeout.Need Check Network".format(e)) + raise ValueError("MQTT Connect error='{}' FAIL".format(e)) + if self.looptask_id is None: + if self.keepalive > 0 and not self.pingFlag: + # Pawn.zhou 2021/1/12 for JIRA STASR3601-2523 begin + task_stacksize = _thread.stack_size() + name,platform = uos.uname()[1].split("=",1) + if platform == "EC600E" or platform == "EC800E": + _thread.stack_size(8 * 1024) + elif platform == "FCM360W" or platform == "FCM362K": + _thread.stack_size(2 * 1024) + else: + _thread.stack_size(16 * 1024) + self.looptask_id = _thread.start_new_thread(self.__loop_forever, ()) + _thread.stack_size(task_stacksize) + self.pingFlag = True + # Pawn.zhou 2021/1/12 for JIRA STASR3601-2523 end + return 0 + + def __loop_forever(self): + while True: + if self.keepalive >= 5: + keepalive = self.keepalive - 3 + try: + if not self.timerFlag: + if self.mqttsendlock is not None and self.mqttsendlock.locked(): + self.mqttsendlock.release() + self.looptask_id = None + break + # time = utime.mktime(utime.localtime()) + time = utime.ticks_ms() // 1000 + + if time - self.last_time > keepalive: + if self.mqttlock.locked(): + utime.sleep(5) + continue + if self.PING == True: + mqtt_log.warning("[%s] Send ping timeout 2. Trying to reconnect" % time) + if not self.reconn: + if self.mqttsendlock is not None and self.mqttsendlock.locked(): + self.mqttsendlock.release() + self.looptask_id = None + raise Exception("Send ping timeout.") + else: + if self.pingnum <= 0: + mqtt_log.warning("[%s] Send ping timeout 1. Trying to reconnect" % time) + self.sock.settimeout(3) + self.pingFlag = False + if self.mqttsendlock is not None and self.mqttsendlock.locked(): + self.mqttsendlock.release() + self.looptask_id = None + break + else: + mqtt_log.warning("[%s] Trying to resend ping(%d)" % (time, self.pingnum)) + self.pingnum = self.pingnum - 1 + while True: + if self.mqttsendlock is not None and self.mqttsendlock.locked(): + utime.sleep_ms(10) + continue + self.mqttsendlock.acquire() + super().ping() + self.mqttsendlock.release() + utime.sleep(5) + break + else: + utime.sleep(5) + continue + except Exception as e: + if self.mqttsendlock is not None and self.mqttsendlock.locked(): + self.mqttsendlock.release() + if not self.timerFlag: + self.looptask_id = None + break + # Network normal, take the initiative to throw exception + if not self.reconn: + if self.error_callback is not None: + self.error_callback(str(e)) + self.pingFlag = False + self.looptask_id = None + break + else: + self.pingFlag = False + self.looptask_id = None + break + # Whether to use the built-in reconnect mechanism + time_info = self.logTime() + if self.PING == True: + mqtt_log.warning("[%s] Send ping timeout 3. Trying to reconnect" % time_info) + else: + mqtt_log.warning("[%s] Send ping, Network exception. Trying to reconnect" % time_info) + utime.sleep(2) + self.base_reconnect() + break + + def logTime(self): + log_time = utime.localtime() + time_info = "%d-%d-%d %d:%d:%d" % ( + log_time[0], log_time[1], log_time[2], log_time[3], log_time[4], log_time[5],) + return time_info diff --git a/ports/quectel/moduos.c b/ports/quectel/moduos.c new file mode 100644 index 0000000000000..26d44011c421f --- /dev/null +++ b/ports/quectel/moduos.c @@ -0,0 +1,240 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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/objstr.h" +#include "py/runtime.h" +#include "py/mperrno.h" +#include "py/mphal.h" +#include "extmod/misc.h" +#include "extmod/vfs.h" +#include "extmod/vfs_lfs.h" +#include "mpversion.h" +#include "helios_dev.h" +#if MICROPY_VFS_QUECFS +#include "vfs_quecfs.h" +#endif + +#if MICROPY_QPY_MODULE_UOS + +static char sysname[30] = {0}; +static char nodename[20] = {0}; +static char machine[30] = {0}; + +extern const mp_obj_type_t mp_fat_vfs_type; + + +static const qstr os_uname_info_fields[] = { + MP_QSTR_sysname, MP_QSTR_nodename,MP_QSTR_release, + MP_QSTR_version, MP_QSTR_machine, MP_QSTR_qpyver, +}; + +static MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, sysname); +static MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, nodename); +static MP_DEFINE_STR_OBJ(os_uname_info_release_obj, MICROPY_VERSION_STRING); +static MP_DEFINE_STR_OBJ(os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE); +static MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, machine); +static MP_DEFINE_STR_OBJ(os_uname_info_qpyver_obj, QUECPYTHON_VERSION_STRING); + +static MP_DEFINE_ATTRTUPLE( + os_uname_info_obj, + os_uname_info_fields, + 6, + (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, + (mp_obj_t)&os_uname_info_qpyver_obj + ); + +static mp_obj_t os_uname2(void) { + Helios_Dev_GetProductName((void *)sysname, sizeof(sysname)); + Helios_Dev_GetModel((void *)nodename, sizeof(nodename)); + snprintf(machine, sizeof(machine), "%s with QUECTEL", nodename); + + os_uname_info_sysname_obj.len = strlen(sysname); + os_uname_info_nodename_obj.len = strlen(nodename); + os_uname_info_machine_obj.len = strlen(machine); + os_uname_info_qpyver_obj.len = strlen(QUECPYTHON_VERSION_STRING); + return (mp_obj_t)&os_uname_info_obj; +} +static MP_DEFINE_CONST_FUN_OBJ_0(os_uname2_obj, os_uname2); + + +static mp_obj_t os_uname(void) { + char sysname[40] = {0}; + char nodname[20] = {0}; + char release[20] = {0}; + char machine[30] = {0}; + char version[128] = {0}; + //char qpy_ver[20] = {0}; + + char mob_usb_product[64] = {0}; + char mob_model_id[64] = {0}; + //char _qpy_ver[20] = {0}; + + Helios_Dev_GetProductName((void *)mob_usb_product, sizeof(mob_usb_product)); + Helios_Dev_GetModel((void *)mob_model_id, sizeof(mob_model_id)); + //Helios_Dev_GetQpyVersion((void *)_qpy_ver, sizeof(_qpy_ver)); + + snprintf(sysname, sizeof(sysname), "sysname=%s", mob_usb_product); + snprintf(nodname, sizeof(nodname), "nodename=%s", mob_model_id); + snprintf(release, sizeof(release), "release=%s", MICROPY_VERSION_STRING); + snprintf(version, sizeof(version), "version=%s on %s", MICROPY_GIT_TAG, MICROPY_BUILD_DATE); + snprintf(machine, sizeof(machine), "machine=%s with QUECTEL", mob_model_id); + //snprintf(qpy_ver, sizeof(qpy_ver), "qpyver=%s", _qpy_ver); + + mp_obj_t tuple[6] = { + mp_obj_new_str(sysname, strlen(sysname)), + mp_obj_new_str(nodname, strlen(nodname)), + mp_obj_new_str(release, strlen(release)), + mp_obj_new_str(version, strlen(version)), + mp_obj_new_str(machine, strlen(machine)), + mp_obj_new_str("qpyver="QUECPYTHON_VERSION_STRING, strlen("qpyver="QUECPYTHON_VERSION_STRING)), + }; + + return mp_obj_new_tuple(6, tuple); +} + + +static MP_DEFINE_CONST_FUN_OBJ_0(os_uname_obj, os_uname); + +#include "quectel_version.h" +static mp_obj_t os_sdkver(void) { +#if defined(PLAT_Qualcomm) + return mp_obj_new_str(mob_sw_rev, strlen(mob_sw_rev)); +#else + extern mp_obj_t queclib_dev_fw_version(); + return queclib_dev_fw_version(); +#endif +} + +static MP_DEFINE_CONST_FUN_OBJ_0(os_sdkver_obj, os_sdkver); + +// 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 OS_URANDOM_SEED_ON_IMPORT (1) +#else +#define OS_URANDOM_SEED_ON_IMPORT (0) +#endif + +#if OS_URANDOM_SEED_ON_IMPORT +static mp_obj_t os_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; + srand(MICROPY_PY_URANDOM_SEED_INIT_FUNC); + } + return mp_const_none; + +} +static MP_DEFINE_CONST_FUN_OBJ_0(os_urandom___init___obj, os_urandom___init__); +#endif + +#if MICROPY_PY_OS_DUPTERM +static mp_obj_t os_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(os_dupterm_notify_obj, os_dupterm_notify); +#endif + +extern const mp_obj_type_t helios_flash_device_type; +static const mp_rom_map_elem_t os_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) }, + #if OS_URANDOM_SEED_ON_IMPORT + { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&os_urandom___init___obj) }, + #endif + { MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&os_uname_obj) }, + { MP_ROM_QSTR(MP_QSTR_uname2), MP_ROM_PTR(&os_uname2_obj) }, + { MP_ROM_QSTR(MP_QSTR_sdkver), MP_ROM_PTR(&os_sdkver_obj) }, + #if MICROPY_PY_OS_DUPTERM + { MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&mp_uos_dupterm_obj) }, + { MP_ROM_QSTR(MP_QSTR_dupterm_notify), MP_ROM_PTR(&os_dupterm_notify_obj) }, + #endif + { MP_ROM_QSTR(MP_QSTR_FlashDevice), MP_ROM_PTR(&helios_flash_device_type) }, + #if MICROPY_VFS + { 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_rmdir), MP_ROM_PTR(&mp_vfs_rmdir_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_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_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_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 defined(PLAT_Qualcomm) + { MP_ROM_QSTR(MP_QSTR_VfsEfs), MP_ROM_PTR(&mp_type_vfs_efs) }, + #endif + #if defined(PLAT_Unisoc_8910_R05) || defined(PLAT_Unisoc_8910_R06) + { MP_ROM_QSTR(MP_QSTR_VfsTemp), MP_ROM_PTR(&mp_type_vfs_temp) }, + #endif + #if defined(PLAT_Unisoc_8910_R05) || defined(PLAT_Unisoc_8910_R06) || (defined(PLAT_Unisoc_8850_R02) && !defined(BOARD_EC800GCN_LD_XBND)) + { MP_ROM_QSTR(MP_QSTR_VfsSd), MP_ROM_PTR(&mp_type_vfs_temp) }, + #endif +#if MICROPY_VFS_FAT_SDIO + { MP_ROM_QSTR(MP_QSTR_VfsEmmc), MP_ROM_PTR(&mp_type_vfs_sdio_emmc) }, + { MP_ROM_QSTR(MP_QSTR_VfsSd), MP_ROM_PTR(&mp_type_vfs_sdio_sd) }, +#endif +#if MICROPY_VFS_QUECFS + { MP_ROM_QSTR(MP_QSTR_VfsQuecfs), MP_ROM_PTR(&mp_type_vfs_quecfs) }, +#endif + #endif +}; + +static MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table); + +const mp_obj_module_t uos_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&os_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_uos, uos_module); +#endif diff --git a/ports/quectel/modussl_mbedtls.c b/ports/quectel/modussl_mbedtls.c new file mode 100644 index 0000000000000..149279d95beff --- /dev/null +++ b/ports/quectel/modussl_mbedtls.c @@ -0,0 +1,600 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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" +#include "mpconfigport.h" + + +#if MICROPY_PY_USSL && MICROPY_SSL_MBEDTLS +#include "mpconfigboard.h" +#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" +#include "mbedtls/x509.h" +#include "helios_debug.h" + +#define QPY_MPUSSL_LOG(msg, ...) custom_log(Ussl, msg, ##__VA_ARGS__) + +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 ca; + 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; +}; + +extern 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; + QPY_MPUSSL_LOG("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_printf(&mp_plat_print, "[mbedtls](write buf = %s ) :\n", buf); + + mp_uint_t out_sz = sock_stream->write(sock, buf, len, &err); + mp_printf(&mp_plat_print, "[mbedtls](write out_sz = %d ) :\n", out_sz); + 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; + } +} + +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_printf(&mp_plat_print, "[mbedtls](read len = %d ) :\n", len); + + mp_uint_t out_sz = sock_stream->read(sock, buf, len, &err); + + mp_printf(&mp_plat_print, "[mbedtls](read out_sz = %d ) :\n", out_sz); + + if (out_sz == MP_STREAM_ERROR) { + if (mp_is_nonblocking_error(err)) { + return MBEDTLS_ERR_SSL_WANT_READ; + } + return -err; + } else { + return out_sz; + } +} + +#define SSL_IGNORE_BADCERT_EXPIRED 0x01 /**< The certificate validity has expired. */ +#define SSL_IGNORE_BADCERT_REVOKED 0x02 /**< The certificate has been revoked (is on a CRL). */ +#define SSL_IGNORE_BADCERT_CN_MISMATCH 0x04 /**< The certificate Common Name (CN) does not match with the expected CN. */ +#define SSL_IGNORE_BADCERT_NOT_TRUSTED 0x08 /**< The certificate is not correctly signed by the trusted CA. */ +#define SSL_IGNORE_BADCRL_NOT_TRUSTED 0x10 /**< The CRL is not correctly signed by the trusted CA. */ +#define SSL_IGNORE_BADCRL_EXPIRED 0x20 /**< The CRL is expired. */ +#define SSL_IGNORE_BADCERT_MISSING 0x40 /**< Certificate was missing. */ +#define SSL_IGNORE_BADCERT_SKIP_VERIFY 0x80 /**< Certificate verification was skipped. */ +#define SSL_IGNORE_BADCERT_FUTURE 0x0200 /**< The certificate validity starts in the future. */ + +static int my_verify( void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags ) +{ + char buf[1024]; + ((void) data); + + mbedtls_x509_crt_info( buf, sizeof( buf ) - 1, "", crt ); + + mp_printf(&mp_plat_print, "[mbedtls](*flags %d error) :\n", *flags); + if(*flags & (SSL_IGNORE_BADCERT_FUTURE)) + { + *flags &= ~(SSL_IGNORE_BADCERT_FUTURE); + return( 0 ); + } + + return *flags; +} + +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); + mp_obj_ssl_socket_t *o = (mp_obj_ssl_socket_t *) m_malloc_with_finaliser(sizeof(mp_obj_ssl_socket_t)); + #endif + + int ret = -1; + o->entropy = (mbedtls_entropy_context *)malloc(sizeof(mbedtls_entropy_context)); + if (o->entropy == NULL){ + goto cleanup; + } + o->ctr_drbg = (mbedtls_ctr_drbg_context *)malloc(sizeof(mbedtls_ctr_drbg_context)); + if (o->ctr_drbg == NULL){ + goto cleanup; + } + o->ssl = (mbedtls_ssl_context *)malloc(sizeof(mbedtls_ssl_context)); + if (o->ssl == NULL){ + goto cleanup; + } + o->conf = (mbedtls_ssl_config *)malloc(sizeof(mbedtls_ssl_config)); + if (o->conf == NULL){ + goto cleanup; + } + o->cacert = (mbedtls_x509_crt *)malloc(sizeof(mbedtls_x509_crt)); + if (o->cacert == NULL){ + goto cleanup; + } + o->cert = (mbedtls_x509_crt *)malloc(sizeof(mbedtls_x509_crt)); + if (o->cert == NULL){ + goto cleanup; + } + o->pkey = (mbedtls_pk_context *)malloc(sizeof(mbedtls_pk_context)); + if (o->pkey == NULL){ + goto cleanup; + } + + o->base.type = &ussl_socket_type; + o->sock = sock; + + mbedtls_platform_setup(NULL); + + 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) + mbedtls_debug_set_threshold(100); + #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->ca.u_obj != mp_const_none) { + size_t cert_len; + const byte *cert = (const byte *)mp_obj_str_get_data(args->ca.u_obj, &cert_len); + + ret = mbedtls_x509_crt_parse(o->cacert, cert, cert_len + 1); + if (ret != 0) { + ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA; // use general error for all cert errors + goto cleanup; + } + + uint32_t flags; + char xcbuf[256]; + memset( xcbuf, 0, 256); + + ret = mbedtls_x509_crt_verify( o->cacert, o->cacert, NULL, NULL, &flags, NULL, NULL ); + if( ret != 0 ) + { + QPY_MPUSSL_LOG("flags: %0x\n", flags); + ret = mbedtls_x509_crt_verify_info(xcbuf, sizeof(xcbuf), "\n", flags); + + if (flags == 0x200) + { + QPY_MPUSSL_LOG("mbedtls_x509_crt_verify IGNORE\n"); + } + else + { + mp_printf(&mp_plat_print, "[mbedtls](mbedtls_x509_crt_verify FAIL: %s) :\n", xcbuf); + ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; // use general error for all cert errors + goto cleanup; + } + } + else + { + QPY_MPUSSL_LOG("mbedtls_x509_crt_verify succeeded\n"); + } + + mbedtls_ssl_conf_ca_chain(o->conf, o->cacert, NULL); + mbedtls_ssl_conf_authmode(o->conf, MBEDTLS_SSL_VERIFY_REQUIRED); + mbedtls_ssl_conf_verify( o->conf, my_verify, 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; + } + } + } + + return MP_OBJ_FROM_PTR(o); + +cleanup: + if (o->pkey != NULL) + { + mbedtls_pk_free(o->pkey); free(o->pkey); o->pkey = NULL; + } + if (o->cert != NULL) + { + mbedtls_x509_crt_free(o->cert); free(o->cert); o->cert = NULL; + } + if (o->cacert != NULL) + { + mbedtls_x509_crt_free(o->cacert); free(o->cacert); o->cacert = NULL; + } + if (o->ssl != NULL) + { + mbedtls_ssl_free(o->ssl); free(o->ssl); o->ssl = NULL; + } + if (o->conf != NULL) + { + mbedtls_ssl_config_free(o->conf); free(o->conf); o->conf = NULL; + } + if (o->ctr_drbg != NULL) + { + mbedtls_ctr_drbg_free(o->ctr_drbg); free(o->ctr_drbg); o->ctr_drbg = NULL; + } + if (o->entropy != NULL) + { + mbedtls_entropy_free(o->entropy); free(o->entropy); o->entropy = NULL; + } + + 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 if (ret == MBEDTLS_ERR_X509_FILE_IO_ERROR) { + mp_raise_ValueError(MP_ERROR_TEXT("invalid ca")); + } 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); + + mp_printf(&mp_plat_print, "[mbedtls_ssl_read](socket_read 1:\n"); + 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); + + mp_printf(&mp_plat_print, "[mbedtls_ssl_write](socket_write 1:\n"); + + 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) { + if (self->pkey) + { + mbedtls_pk_free(self->pkey); + free(self->pkey); + self->pkey = NULL; + } + if (self->cert) + { + mbedtls_x509_crt_free(self->cert); + free(self->cert); + self->cert = NULL; + } + if (self->cacert) + { + mbedtls_x509_crt_free(self->cacert); + free(self->cacert); + self->cacert = NULL; + } + if (self->ssl) + { + mbedtls_ssl_free(self->ssl); + free(self->ssl); + self->ssl = NULL; + } + if (self->conf) + { + mbedtls_ssl_config_free(self->conf); + free(self->conf); + self->conf = NULL; + } + if (self->ctr_drbg) + { + mbedtls_ctr_drbg_free(self->ctr_drbg); + free(self->ctr_drbg); + self->ctr_drbg = NULL; + } + if (self->entropy) + { + mbedtls_entropy_free(self->entropy); + free(self->entropy); + self->entropy = NULL; + } + } + // 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, +}; + +MP_DEFINE_CONST_OBJ_TYPE( + ussl_socket_type, + MP_QSTR_ussl, + MP_TYPE_FLAG_NONE, + protocol, &ussl_socket_stream_p, + locals_dict, &ussl_socket_locals_dict + ); + +bool mp_obj_is_ussl_socket(mp_obj_t o) { + return mp_obj_is_type(o, &ussl_socket_type); +} + +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_ca, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { 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 diff --git a/ports/quectel/modutime.c b/ports/quectel/modutime.c new file mode 100644 index 0000000000000..1de09e4f5bea7 --- /dev/null +++ b/ports/quectel/modutime.c @@ -0,0 +1,220 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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 "shared/timeutils/timeutils.h" +#include "utime_mphal.h" + +#if MICROPY_QPY_MODULE_UTIME + +#include "helios_debug.h" +#include "helios_rtc.h" + + +#define QPY_UTIME_LOG(msg, ...) custom_log(utime, msg, ##__VA_ARGS__) + +static mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) { + timeutils_struct_time_t tm; + int64_t seconds; + if (n_args == 0 || args[0] == mp_const_none) { + Helios_RTCTime rtc_tm = {0, 0, 0, 1, 1, 1970, 4}; + Helios_RTC_GetLocalTime(&rtc_tm); + seconds = timeutils_seconds_since_2000(rtc_tm.tm_year, rtc_tm.tm_mon, rtc_tm.tm_mday, rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec); + timeutils_seconds_since_2000_to_struct_time(seconds, &tm); + } + else + { + //modified by freddy @20211227 Fix the exception when c=utime.mktime(utime.localtime()) utime.localtime(c) is executed when no network is injected + seconds = mp_obj_get_int_truncated(args[0]) - 946656000; // Pawn - 2021-03-17 -Fixed bug:Return time error + // Pawn - 2020-12-10 -Fixed bug:Return time error + timeutils_seconds_since_2000_to_struct_time(seconds, &tm); + if (tm.tm_hour >= 24) + { + tm.tm_mday += 1; + tm.tm_hour = tm.tm_hour % 24; + + switch (tm.tm_mon) + { + case 1: + case 3: + case 5: + case 7: + case 8: + case 10: + case 12: + if (tm.tm_mday > 31) + { + tm.tm_mon += 1; + tm.tm_mday = tm.tm_mday % 31; + } + break; + case 4: + case 6: + case 9: + case 11: + if (tm.tm_mday > 30) + { + tm.tm_mon += 1; + tm.tm_mday = tm.tm_mday % 30; + } + break; + case 2: + if (((tm.tm_year%4 == 0) && (tm.tm_year%100 != 0)) || (tm.tm_year%400 == 0)) + { + if (tm.tm_mday > 29) + { + tm.tm_mon += 1; + tm.tm_mday = tm.tm_mday % 29; + } + } + else + { + if (tm.tm_mday > 28) + { + tm.tm_mon += 1; + tm.tm_mday = tm.tm_mday % 28; + } + } + break; + default: + QPY_UTIME_LOG("the value(%d) of month is invalid.\n", tm.tm_mon); + break; + } + + if (tm.tm_mon > 12) + { + tm.tm_year += 1; + tm.tm_mon = tm.tm_mon % 12; + } + } + } + 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); + Helios_RTCTime rtc_tm; + mp_uint_t time_unix; + // 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); + } + rtc_tm.tm_year = mp_obj_get_int(elem[0]); + rtc_tm.tm_mon = mp_obj_get_int(elem[1]); + rtc_tm.tm_mday = mp_obj_get_int(elem[2]); + rtc_tm.tm_hour = mp_obj_get_int(elem[3]); + rtc_tm.tm_min = mp_obj_get_int(elem[4]); + rtc_tm.tm_sec = mp_obj_get_int(elem[5]); + + if (0 >= (rtc_tm.tm_mon -= 2)) { /* 1..12 -> 11,12,1..10 */ + rtc_tm.tm_mon += 12; /* Puts Feb last since it has leap day */ + rtc_tm.tm_year -= 1; + } + time_unix = ((( + ( mp_uint_t ) (rtc_tm.tm_year/4 - rtc_tm.tm_year/100 + rtc_tm.tm_year/400 + + 367*rtc_tm.tm_mon/12 + rtc_tm.tm_mday) + rtc_tm.tm_year*365 - 719499)*24 + + rtc_tm.tm_hour)*60 + rtc_tm.tm_min)*60 + rtc_tm.tm_sec - 28800; + + return mp_obj_new_int_from_uint(time_unix); +} +static MP_DEFINE_CONST_FUN_OBJ_1(time_mktime_obj, time_mktime); + +/*return rtc seconds since power on*/ +static mp_obj_t time_time(void) +{ + long seconds=0; + seconds = Helios_RTC_GetSecond(); + return mp_obj_new_int(seconds); +} +MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time); + +#if 1 +static mp_obj_t time_set_timezone(mp_obj_t tz) +{ + int offset = mp_obj_get_int(tz); + if ((offset < -12) || (offset > 12)) + { + mp_raise_ValueError(MP_ERROR_TEXT("invalid value, timezone should be in [-12, +12].")); + } + Helios_RTC_SetTimeZoneOffset(offset); + return mp_obj_new_int(0); +} +static MP_DEFINE_CONST_FUN_OBJ_1(time_set_timezone_obj, time_set_timezone); +#endif + +static mp_obj_t time_get_timezone(void) +{ + int offset = Helios_RTC_GetTimeZoneOffset(); + return mp_obj_new_int(offset); +} +static MP_DEFINE_CONST_FUN_OBJ_0(time_get_timezone_obj, time_get_timezone); + + + +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_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_setTimeZone), MP_ROM_PTR(&time_set_timezone_obj) }, + { MP_ROM_QSTR(MP_QSTR_getTimeZone), MP_ROM_PTR(&time_get_timezone_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); + +#endif /* MICROPY_QPY_MODULE_UTIME */ diff --git a/ports/quectel/mpconfigport.h b/ports/quectel/mpconfigport.h new file mode 100644 index 0000000000000..6cf8f636ec24e --- /dev/null +++ b/ports/quectel/mpconfigport.h @@ -0,0 +1,241 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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 "mpconfigboard.h" + +/****************************** user define ************************************/ +// python grammar +#define MICROPY_PY_ATTRTUPLE (1) +#define MICROPY_PY_BUILTINS_BYTEARRAY (1) +#define MICROPY_CPYTHON_COMPAT (1) + +// builtin op +#define MICROPY_PY_BUILTINS_STR_OP_MODULO (1) +#define MICROPY_PY_BUILTINS_HELP (1) +#define MICROPY_PY_BUILTINS_HELP_TEXT quecpython_help_text +#define MICROPY_PY_BUILTINS_HELP_MODULES (1) + +// modules +#define MICROPY_PY_IO (1) +#define MICROPY_PY_JSON (1) +#define MICROPY_VFS (1) +#define MICROPY_PY_VFS (0) +#define MICROPY_PY_TIME (0) +#define MICROPY_PY_HEAPQ (0) +#define MICROPY_PY_OS (0) +#define MICROPY_PY_PLATFORM (0) +#define MICROPY_PY_SELECT (0) +#define MICROPY_PY_FRAMEBUF (0) +#define MICROPY_PY_ASYNCIO (0) +#define MICROPY_PY_BINASCII_CRC32 (0) + +#define MICROPY_PY_UCTYPES (MICROPY_QPY_PY_UCTYPES) +#define MICROPY_PY_DEFLATE (0) + +#define MICROPY_OPT_COMPUTED_GOTO (1) + +/******************************** base define **********************************/ +// options to control how MicroPython is built + +// Use the minimal starting configuration (disables all optional features). +#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES) + +// You can disable the built-in MicroPython compiler by setting the following +// config option to 0. If you do this then you won't get a REPL prompt, but you +// will still be able to execute pre-compiled scripts, compiled with mpy-cross. +#define MICROPY_ENABLE_COMPILER (1) + +#define MICROPY_ENABLE_GC (1) +#define MICROPY_PY_GC (1) +#define MICROPY_HELPER_REPL (1) +#define MICROPY_ENABLE_EXTERNAL_IMPORT (1) +#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) +#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE) //decimal numbers support +#define MICROPY_USE_INTERNAL_PRINTF (0) +#define MPZ_DIG_SIZE (16) +#define MICROPY_PY_SYS (1) + +#define MICROPY_ALLOC_PATH_MAX (256) +#define MICROPY_ALLOC_PARSE_CHUNK_INIT (16) + +#define MICROPY_ERROR_REPORTING MICROPY_ERROR_REPORTING_NORMAL +#define MICROPY_USE_INTERNAL_ERRNO (1) +#define MICROPY_ENABLE_SCHEDULER (1) +#define MICROPY_SCHEDULER_STATIC_NODES (0) +#define MICROPY_SCHEDULER_DEPTH (64)//8 +#define MICROPY_REPL_AUTO_INDENT (1) +#define MICROPY_PY_UTIME_MP_HAL (1) + + +#define MICROPY_PY_THREAD (1) +#define MICROPY_PY_THREAD_GIL (1) +#define MICROPY_ENABLE_CALLBACK_DEAL (1) +#define MICROPY_READER_VFS (1) + +#define MICROPY_KBD_EXCEPTION (1) +#define MICROPY_PY_SOFT_RESET (0) +#define MICROPY_PY_IO_FILEIO (1) +#define MICROPY_PY_BUILTINS_SLICE (1) +#define MICROPY_PY_BUILTINS_PROPERTY (1) +#define MICROPY_PY_BUILTINS_BYTEARRAY (1) +#define MICROPY_PY_BUILTINS_SET (1) +#define MICROPY_PY_BUILTINS_MEMORYVIEW (1) +#define MICROPY_PY_SYS_STDFILES (1) +#define MICROPY_PY_SYS_STDIO_BUFFER (1) +#define MICROPY_PY_STRUCT (1) +#define MICROPY_ENABLE_FINALISER (1) +#define MICROPY_PY_BUILTINS_ENUMERATE (1) +#define MICROPY_PY_BUILTINS_MIN_MAX (1) +#if defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) +#define MICROPY_PY_URANDOM (1) +#define MICROPY_PY_URANDOM_EXTRA_FUNCS (1) +#endif + +#define MICROPY_PERSISTENT_CODE_LOAD (1) +#define MICROPY_PY_MICROPYTHON (1) +#define MICROPY_PY_MICROPYTHON_MEM_INFO (1) + +#ifndef SSIZE_MAX +#define SSIZE_MAX 0xFFFFFFFF +#endif + +#if defined(PLAT_Unisoc) \ + || defined(PLAT_Unisoc_8850) \ + || defined(PLAT_ASR_1803s) \ + || defined(PLAT_RDA) \ + || defined(PLAT_Qualcomm) \ + || defined(PLAT_ASR) +#define MICROPY_PY_REPL_PASSWORD_PROTECT (1) +#endif + +#if defined(PLAT_SONY_ALT1350) +#define MICROPY_PY_USOCKET_EVENTS (1) +#endif + +#if defined(PLAT_SONY_ALT1350) +#define MICROPY_PY_USSL (1) +#define MICROPY_SSL_MBEDTLS (1) +#endif + +#if defined(PLAT_Qualcomm) +#define mp_type_fileio mp_type_vfs_efs_fileio +#define mp_type_textio mp_type_vfs_efs_textio +#elif defined(PLAT_EIGEN) +#define mp_type_fileio mp_type_vfs_lfs2_fileio +#define mp_type_textio mp_type_vfs_lfs2_textio +#elif defined(PLAT_EIGEN_718) +#define mp_type_fileio mp_type_vfs_lfs2_fileio +#define mp_type_textio mp_type_vfs_lfs2_textio +#else +#define mp_type_fileio mp_type_vfs_lfs1_fileio +#define mp_type_textio mp_type_vfs_lfs1_textio +#endif + + +// 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; +#define UINT_FMT "%lu" +#define INT_FMT "%ld" + + +#if MICROPY_ENABLE_GC +#ifndef MICROPY_QPY_GC_HEAP_SIZE +#define MICROPY_QPY_GC_HEAP_SIZE (512 * 1024) +#endif +#define MICROPY_GC_HEAP_SIZE (MICROPY_QPY_GC_HEAP_SIZE) +#endif + +#ifdef MICROPY_QPY_MAIN_TASK_STACK_SIZE +#define MP_QPY_TASK_STACK_SIZE (MICROPY_QPY_MAIN_TASK_STACK_SIZE) +#else +#if defined(PLAT_RDA) +#define MP_QPY_TASK_STACK_SIZE (32 * 1024) +#elif defined(PLAT_EIGEN) +#define MP_QPY_TASK_STACK_SIZE (32 * 1024) +#elif defined(PLAT_EIGEN_718) +#define MP_QPY_TASK_STACK_SIZE (8 * 1024) +#elif defined(PLAT_ECR6600) +#define MP_QPY_TASK_STACK_SIZE (8 * 1024) +#elif defined(PLAT_aic8800m40) +#define MP_QPY_TASK_STACK_SIZE (10 * 1024) +#elif defined(PLAT_Unisoc_8850) || defined(PLAT_Unisoc_8850_R02) + #if defined(BOARD_EC600GCN_LD) || defined(BOARD_EC800GCN_LD) || defined(BOARD_EC800GCN_LD_XBND) \ + || defined(BOARD_EC800GCN_LD_HRXM) || defined(BOARD_EC600GCN_LD_YM) || defined(BOARD_EC800GCN_TT) \ + || defined(BOARD_EG800GLA_LD) + #define MP_QPY_TASK_STACK_SIZE (16 * 1024) + #else + #define MP_QPY_TASK_STACK_SIZE (64 * 1024) + #endif +#else +#define MP_QPY_TASK_STACK_SIZE (64 * 1024) +#endif +#endif + + +// We need to provide a declaration/definition of alloca() +#include + +#define STRINGIFY_VALUE(s) STRINGIFY(s) +#define STRINGIFY(s) #s +#define MICROPY_HW_BOARD_NAME STRINGIFY_VALUE(BOARD) +#define MICROPY_HW_MCU_NAME "QUECTEL" +// board specifics +#define MICROPY_PY_SYS_PLATFORM STRINGIFY_VALUE(BOARD) +#define QUECPYTHON_VERSION_STRING STRINGIFY_VALUE(QPYVER) + +#ifdef __linux__ +#define MICROPY_MIN_USE_STDOUT (1) +#endif + +#ifdef __thumb__ +#define MICROPY_MIN_USE_CORTEX_CPU (0) +#define MICROPY_MIN_USE_STM32_MCU (0) +#endif + +#define MP_STATE_PORT MP_STATE_VM + + +#if MICROPY_PY_THREAD +#define MICROPY_EVENT_POLL_HOOK \ + do { \ + extern void mp_handle_pending(bool); \ + mp_handle_pending(true); \ + MP_THREAD_GIL_EXIT(); \ + MP_THREAD_GIL_ENTER(); \ + } while (0); +#else +#define MICROPY_EVENT_POLL_HOOK \ + do { \ + extern void mp_handle_pending(bool); \ + mp_handle_pending(true); \ + asm ("waiti 0"); \ + } while (0); +#endif diff --git a/ports/quectel/mpconfigport.mk b/ports/quectel/mpconfigport.mk new file mode 100644 index 0000000000000..3eb1116478c94 --- /dev/null +++ b/ports/quectel/mpconfigport.mk @@ -0,0 +1,51 @@ +# Enable/disable modules and 3rd-party libs to be included in interpreter + +ifeq ($(strip $(PLAT)), $(filter $(PLAT),EIGEN EIGEN_718)) + +MICROPY_VFS_LFS1=0 +MICROPY_VFS_LFS2=1 + +else ifeq ($(strip $(PLAT)), $(filter $(PLAT),Unisoc_8850 Unisoc_8850_R02)) + +MICROPY_VFS_LFS1=1 +MICROPY_VFS_LFS2=0 + +else ifeq ($(strip $(PLAT)), $(filter $(PLAT),Unisoc Unisoc_8910_R05 Unisoc_8910_R06)) + +MICROPY_VFS_LFS1=1 +MICROPY_VFS_LFS2=0 + +else ifeq ($(strip $(PLAT)), $(filter $(PLAT),SONY SONY_ALT1350)) + +MICROPY_VFS_LFS1=0 +MICROPY_VFS_LFS2=0 +MICROPY_VFS_QUECFS=1 + +else ifeq ($(strip $(PLAT)), $(filter $(PLAT),ASR_1602 ASR_1609)) + +MICROPY_VFS_LFS1=0 +MICROPY_VFS_LFS2=1 + +else ifeq ($(strip $(PLAT)), $(filter $(PLAT),ASR ASR_1803s ASR_1803sc)) + +MICROPY_VFS_LFS1=1 +MICROPY_VFS_LFS2=0 + +else ifeq ($(strip $(PLAT)),ASR_1606) + +include $(TOP)/../../system/platform/ASR_1606/board/$(BOARD)/mpconfigboard.mk + +ifeq ($(MICROPY_VFS_LFS_VERSION), 1) +MICROPY_VFS_LFS1=1 +MICROPY_VFS_LFS2=0 +else +MICROPY_VFS_LFS1=0 +MICROPY_VFS_LFS2=1 +endif + +else + +MICROPY_VFS_LFS1=0 +MICROPY_VFS_LFS2=1 + +endif diff --git a/ports/quectel/mphalport.c b/ports/quectel/mphalport.c new file mode 100644 index 0000000000000..e7f4591ce10c1 --- /dev/null +++ b/ports/quectel/mphalport.c @@ -0,0 +1,384 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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/stream.h" +#include "py/obj.h" +#include "py/mphal.h" +#include "py/builtin.h" +#include "py/parse.h" +#include "py/ringbuf.h" +#include "py/mpthread.h" +#include "mphalport.h" + +#include "mpconfigport.h" +#include "helios_uart.h" +#include "helios_rtc.h" +#if MICROPY_PY_KBD_EXCEPTION +#include "shared/runtime/interrupt_char.h" +#include "py/runtime.h" +#endif + +#define QPY_MTHREAD_SLEEP_DEAL_MSG_MAX_NUM (2 * MICROPY_SCHEDULER_DEPTH) +static Helios_MsgQ_t qpy_mthread_sleep_queue = 0; +static int mthread_sleep_flag = 0; + +#define MTHREAD_SLEEP_ENTER() (mthread_sleep_flag = 1) +#define MTHREAD_SLEEP_EXIT() (mthread_sleep_flag = 0) +#define IS_MTHREAD_IN_SLEEP() (1 == mthread_sleep_flag) +#define MP_HAL_PORT_CHECK_OPEN (mp_hal_cdcPort_State == 1) + +static uint8_t stdin_ringbuf_array[256]; +ringbuf_t stdin_ringbuf = {stdin_ringbuf_array, sizeof(stdin_ringbuf_array), 0, 0}; + +//mia.zhong @20220308 fix input of multi thread dump problem. +Input_ListNode_t *Head_node = NULL; +static uint8_t mp_hal_cdcPort_State = 1; + + +static bool mp_mthread_sleep_deal_is_inited(void); +static void mp_hal_stdin_cb(uint64_t ind_type, Helios_UARTNum port, uint64_t size); + + +void mp_hal_port_open(uint8_t state) +{ + mp_hal_cdcPort_State = state; + Helios_UARTConfig UARTConfig = { + HELIOS_UART_BAUD, + HELIOS_UART_DATABIT_8, + HELIOS_UART_STOP_1, + HELIOS_UART_PARITY_NONE, + HELIOS_UART_FC_NONE + }; + Helios_UARTInitStruct UARTInitStruct = {&UARTConfig, mp_hal_stdin_cb}; + + if(state == 1) { + Helios_UART_Deinit(QPY_REPL_UART); + if (Helios_UART_Init(QPY_REPL_UART, &UARTInitStruct)) { + mp_hal_cdcPort_State = 0; + } + } +} + + +//mia.zhong @20220308 fix input of multi thread dump problem. +static bool mp_mthread_sleep_deal_is_inited_child(Input_ListNode_t *node) +{ + return (0 != node->msg_q); +} + +//mia.zhong @20220308 fix input of multi thread dump problem. +int mp_mthread_sleep_child(uint32_t ms) +{ + mp_uint_t msg; + int ret = -1; + if(Head_node) { + if(mp_mthread_sleep_deal_is_inited_child((Input_ListNode_t *)Head_node)) { + Head_node->mthread_sleep_flag = 1; + ret = Helios_MsgQ_Get(Head_node->msg_q, (mp_uint_t*)&msg, sizeof(msg), ms); + Head_node->mthread_sleep_flag = 0; + } + } + return ret; +} +//mia.zhong @20220308 fix input of multi thread dump problem. +void mp_mthread_wakeup_child(void) +{ + mp_uint_t msg = 0; + if(Head_node) { + if(mp_mthread_sleep_deal_is_inited_child((Input_ListNode_t *)Head_node) && (Head_node->mthread_sleep_flag == 1)) { + Helios_MsgQ_Put(Head_node->msg_q, (const void*)(&msg), sizeof(mp_uint_t), 0); + } + } +} + +//main thread sleep +int mp_mthread_sleep(uint32_t ms) +{ + mp_uint_t msg; + int ret = -1; + if(mp_mthread_sleep_deal_is_inited()) { + MTHREAD_SLEEP_ENTER(); + ret = Helios_MsgQ_Get(qpy_mthread_sleep_queue, (mp_uint_t*)&msg, sizeof(msg), ms); + MTHREAD_SLEEP_EXIT(); + } + return ret; +} + +//wake up main sleep +void mp_mthread_wakeup(void) +{ + mp_uint_t msg = 0; + if(mp_mthread_sleep_deal_is_inited() && (IS_MTHREAD_IN_SLEEP())) { + Helios_MsgQ_Put(qpy_mthread_sleep_queue, (const void*)(&msg), sizeof(mp_uint_t), 0); + } +} + +void mp_main_thread_wakeup() +{ + //mia.zhong @20220308 fix input of multi thread dump problem. + if (Head_node != NULL) { + mp_mthread_wakeup_child(); + } else { + mp_mthread_wakeup();//forrest.liu@20210809 add for quecpython task repl using waiting msg + } +} + +static void mp_hal_stdin_cb(uint64_t ind_type, Helios_UARTNum port, uint64_t size) +{ + if(MP_HAL_PORT_CHECK_OPEN) { +#if MICROPY_PY_KBD_EXCEPTION + if(IS_MAINPY_RUNNING_FLAG_TRUE() && Head_node == NULL) + { + uint64_t i = 0; + volatile unsigned char c = 0; + for(i= 0; i < size; i++) + { + if(Helios_UART_Read(QPY_REPL_UART, (void *)&c, sizeof(unsigned char)) >0 ) { + if (!IS_REPL_REFUSED() && (c == mp_interrupt_char)) { + // Signal keyboard interrupt to be raised as soon as the VM resumes + mp_sched_keyboard_interrupt(); + break; + } + continue; + } + break; + } + if(i < size) + { + for(; i < size; i++) + { + if(Helios_UART_Read(QPY_REPL_UART, (void *)&c, sizeof(unsigned char)) >0 ) { + continue; + } + break; + } + } + } + else +#endif + { + mp_main_thread_wakeup(); + + } + } +} + +int mp_hal_stdio_init(void) +{ + Helios_UARTConfig UARTConfig = { + HELIOS_UART_BAUD_115200, + HELIOS_UART_DATABIT_8, + HELIOS_UART_STOP_1, + HELIOS_UART_PARITY_NONE, + HELIOS_UART_FC_NONE + }; + + Helios_UARTInitStruct UARTInitStruct = {&UARTConfig, mp_hal_stdin_cb}; + int ret = (int)Helios_UART_Init(QPY_REPL_UART, &UARTInitStruct); + if(ret) + { + return -1; + } + return 0; +} + +int mp_hal_stdin_rx_chr(void) +{ + while(1) + { + volatile unsigned char c = 0; + + if(MP_HAL_PORT_CHECK_OPEN && Helios_UART_Read(QPY_REPL_UART, (void *)&c, sizeof(unsigned char)) >0 ) { + return c; + } + + //forrest.liu@20210809 add for quecpython task repl using waiting msg + MP_THREAD_GIL_EXIT(); + //mia.zhong @20220308 fix input of multi thread dump problem. + if (Head_node != NULL) + mp_mthread_sleep_child(HELIOS_WAIT_FOREVER); + else + mp_mthread_sleep(HELIOS_WAIT_FOREVER); + MP_THREAD_GIL_ENTER(); + + MICROPY_EVENT_POLL_HOOK + } +} + +mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) +{ + if (!str|| !len) return 0; + if(MP_HAL_PORT_CHECK_OPEN) { + Helios_UART_Write(QPY_REPL_UART, (void *)str, len); + } + return len; +} + +mp_uint_t mp_hal_ticks_ms(void) +{ + return (mp_uint_t)Helios_RTC_TicksToMs(); +} + +mp_uint_t mp_hal_ticks_us(void) +{ + return (mp_uint_t)Helios_RTC_TicksToUs(); +} + +uint64_t mp_hal_time_ns(void) +{ + return 0; +} + +void mp_hal_delay_ms(mp_uint_t ms) { + mp_uint_t dt = 0; + mp_uint_t t0 = 0,t1 = 0; + Helios_Thread_t taskid = 0; + extern Helios_Thread_t ql_micropython_task_ref; + taskid = Helios_Thread_GetID(); + mp_uint_t qpy_mthread_sleep_deal_fun(mp_uint_t ms); + + if(ql_micropython_task_ref == taskid) + { + for(;;) + { + t0 = mp_hal_ticks_us(); + MP_THREAD_GIL_EXIT(); + mp_uint_t wait_time = qpy_mthread_sleep_deal_fun(ms); + MP_THREAD_GIL_ENTER(); + if(wait_time >= ms) + { + return; + } + MICROPY_EVENT_POLL_HOOK; + t1 = mp_hal_ticks_us(); + dt = t1 - t0; + if(dt / 1000 >= ms) + { + return; + } + ms -= dt / 1000; + } + } + else + { + MP_THREAD_GIL_EXIT(); + Helios_msleep(ms); + MP_THREAD_GIL_ENTER(); + } +} + +void mp_hal_delay_us(mp_uint_t us) { + mp_uint_t ms = us / 1000; + ms = ms ? ms : 1; + mp_hal_delay_ms(ms); +} + +mp_uint_t mp_hal_ticks_cpu(void) { + return (mp_uint_t)Helios_RTC_GetTicks(); +} + + +uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { + uintptr_t ret = 0; + if ((poll_flags & MP_STREAM_POLL_RD) && stdin_ringbuf.iget != stdin_ringbuf.iput) { + ret |= MP_STREAM_POLL_RD; + } + return ret; +} + +mp_uint_t qpy_mthread_sleep_deal_fun(mp_uint_t ms) +{ + if(mp_mthread_sleep_deal_is_inited()) + { + mp_uint_t dt; + mp_uint_t t0 = mp_hal_ticks_us(); + int ret = mp_mthread_sleep(ms); + if(ret < 0) + { + return ms; + } + else + { + mp_uint_t t1 = mp_hal_ticks_us(); + dt = t1 - t0; + return dt / 1000; + } + } + else + { + Helios_msleep(ms); + return ms; + } +} + +//mia.zhong @20220308 fix input of multi thread dump problem. +void _add_list_node() +{ + Input_ListNode_t *node = (Input_ListNode_t *)malloc(sizeof(Input_ListNode_t)); + memset(node, 0, sizeof(Input_ListNode_t)); + + if(0 == node->msg_q) { + node->msg_q = Helios_MsgQ_Create(QPY_MTHREAD_SLEEP_DEAL_MSG_MAX_NUM, sizeof(mp_uint_t)); + } + node->next_node = Head_node; + Head_node = node; +} + +//mia.zhong @20220308 fix input of multi thread dump problem. +void _delete_list_node()//delete node +{ + Input_ListNode_t *node = NULL; + + if (Head_node) { + if(0 != Head_node->msg_q) { + Helios_MsgQ_Delete(Head_node->msg_q); + } + node = Head_node; + Head_node = (Input_ListNode_t *)Head_node->next_node; + node->next_node = NULL; + if (node) { + free(node); + node = NULL; + } + } +} + +void mp_mthread_sleep_deal_init(void) +{ + if(0 == qpy_mthread_sleep_queue) { + qpy_mthread_sleep_queue = \ + Helios_MsgQ_Create(QPY_MTHREAD_SLEEP_DEAL_MSG_MAX_NUM, sizeof(mp_uint_t)); + } +} + +static bool mp_mthread_sleep_deal_is_inited(void) +{ + return (0 != qpy_mthread_sleep_queue); +} + diff --git a/ports/quectel/mphalport.h b/ports/quectel/mphalport.h new file mode 100644 index 0000000000000..21375137df4c3 --- /dev/null +++ b/ports/quectel/mphalport.h @@ -0,0 +1,88 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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 __MPHAL_PORT_H +#define __MPHAL_PORT_H + +#include "helios_os.h" +#include "helios_uart.h" + +#if defined(PLAT_RDA) +#define QPY_REPL_UART HELIOS_UART0 +#define HAL_TICK1S 16.384 +/*Due to low power consumption of BC25 series, the baud rate needs to be set to 57600, please do not modify.*/ +#define HELIOS_UART_BAUD HELIOS_UART_BAUD_57600 +#elif defined(PLAT_Qualcomm) +#define HAL_TICK1S 32.768 +#define QPY_REPL_UART HELIOS_UART3 +#define HELIOS_UART_BAUD HELIOS_UART_BAUD_115200 +#elif defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) +#define HAL_TICK1S 3.25 +#define QPY_REPL_UART HELIOS_UART3 +#define HELIOS_UART_BAUD HELIOS_UART_BAUD_115200 +#elif defined(PLAT_ECR6600) +#define HAL_TICK1S 0.5 +#define QPY_REPL_UART HELIOS_UART2 +#define HELIOS_UART_BAUD HELIOS_UART_BAUD_115200 +#elif defined(PLAT_aic8800m40) +#define HAL_TICK1S 32.768 +#define QPY_REPL_UART HELIOS_UART1 +#define HELIOS_UART_BAUD HELIOS_UART_BAUD_115200 +#else +#define HAL_TICK1S 32.768 +#define QPY_REPL_UART HELIOS_UART3 +#define HELIOS_UART_BAUD HELIOS_UART_BAUD_115200 +#endif + +//mia.zhong @20220308 input接口多线程调用导致dump问题 +typedef struct Input_ListNode +{ + //int id; + int mthread_sleep_flag; + Helios_MsgQ_t msg_q; + void *next_node; +} Input_ListNode_t; + +void _add_list_node(); +void _delete_list_node(); +mp_uint_t mp_hal_ticks_cpu(void); + +void mp_mthread_sleep_deal_init(void); +int mp_mthread_sleep(uint32_t ms); +void mp_mthread_wakeup(void); +int mp_mthread_sleep_child(uint32_t ms); +void mp_mthread_wakeup_child(void); + +int mp_hal_stdio_init(void); + +int mp_hal_stdin_rx_chr(void); + +void mp_hal_port_open(uint8_t state); + +void mp_hal_set_interrupt_char(int c); + +uint64_t mp_hal_time_ns(void); +#endif diff --git a/ports/quectel/mpthreadport.c b/ports/quectel/mpthreadport.c new file mode 100644 index 0000000000000..d8312b767303b --- /dev/null +++ b/ports/quectel/mpthreadport.c @@ -0,0 +1,334 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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 "stdio.h" + +#include "py/runtime.h" +#include "py/gc.h" +#include "py/mpthread.h" +#include "py/mphal.h" +#include "mpthreadport.h" +#include "helios_os.h" + +#if MICROPY_PY_THREAD + +// this structure forms a linked list, one node per active thread +typedef struct _thread_t { + Helios_Thread_t id; // system id of thread + int ready; // whether the thread is ready and running + void *arg; // thread Python args, a GC root pointer + void *stack; // pointer to the stack + size_t stack_len; // number of words in the stack + struct _thread_t *next; +} thread_t; + +// the mutex controls access to the linked list +static mp_thread_mutex_t thread_mutex = 0; +static thread_t thread_entry0; +static thread_t *thread = NULL; // root pointer, handled by mp_thread_gc_others + +void mp_thread_init(void *stack, uint32_t stack_len) { + mp_thread_set_state(&mp_state_ctx.thread); + // create the first entry in the linked list of all threads + thread = &thread_entry0; + thread->id = Helios_Thread_GetID(); + thread->ready = 1; + thread->arg = NULL; + thread->stack = stack; + thread->stack_len = stack_len; + thread->next = NULL; + mp_thread_mutex_init(&thread_mutex); +} + +void _vPortCleanUpTCB(void *tcb) { + if (thread == NULL) { + // threading not yet initialised + return; + } + thread_t *prev = NULL; + mp_thread_mutex_lock(&thread_mutex, 1); + for (thread_t *th = thread; th != NULL; prev = th, th = th->next) { + // unlink the node from the list + if ((void *)th->id == tcb) { + if (prev != NULL) { + prev->next = th->next; + } else { + // move the start pointer + thread = th->next; + } + // explicitly release all its memory + m_del(thread_t, th, 1); + break; + } + } + mp_thread_mutex_unlock(&thread_mutex); +} + +void mp_thread_gc_others(void) { + mp_thread_mutex_lock(&thread_mutex, 1); + for (thread_t *th = thread; th != NULL; th = th->next) { + gc_collect_root((void **)&th, 1); + gc_collect_root(&th->arg, 1); // probably not needed + if (th->id == Helios_Thread_GetID()) { + continue; + } + if (!th->ready) { + continue; + } + gc_collect_root(th->stack, th->stack_len); // probably not needed + } + mp_thread_mutex_unlock(&thread_mutex); +} + +mp_state_thread_t *mp_thread_get_state(void) { + return (mp_state_thread_t *)Helios_Thread_GetSpecific(); +} + +void mp_thread_set_state(mp_state_thread_t *state) { + Helios_Thread_SetSpecific((mp_state_thread_t *)state); +} + +void mp_thread_start(void) { + mp_thread_mutex_lock(&thread_mutex, 1); + for (thread_t *th = thread; th != NULL; th = th->next) { + if (th->id == Helios_Thread_GetID()) { + th->ready = 1; + break; + } + } + mp_thread_mutex_unlock(&thread_mutex); +} + +static void *(*ext_thread_entry)(void *) = NULL; +static void thread_entry(void *arg) { + if (ext_thread_entry) { + ext_thread_entry(arg); + } + _vPortCleanUpTCB((void*)Helios_Thread_GetID()); + Helios_Thread_Exit(); +} + + +int mp_thread_create_ex(void *(*entry)(void *), void *arg, size_t *stack_size, int priority, char *name) { + // store thread entry function into a global variable so we can access it + ext_thread_entry = entry; + if (*stack_size == 0) { + *stack_size = MP_THREAD_DEFAULT_STACK_SIZE; // default stack size + } else if (*stack_size < MP_THREAD_MIN_STACK_SIZE) { + *stack_size = MP_THREAD_MIN_STACK_SIZE; // minimum stack size + } + + // Allocate linked-list node (must be outside thread_mutex lock) + thread_t *th = m_new_obj(thread_t); + + mp_thread_mutex_lock(&thread_mutex, 1); + + // create thread + Helios_ThreadAttr ThreadAttr = { + .name = name, + .stack_size = *stack_size / sizeof(uint32_t), + .priority = priority, + .entry = thread_entry, + .argv = arg + }; + Helios_Thread_t thread_id = Helios_Thread_Create(&ThreadAttr); + if(thread_id == 0) + { + mp_thread_mutex_unlock(&thread_mutex); + mp_raise_msg(&mp_type_OSError, (mp_rom_error_text_t)"can't create thread"); + } + + // add thread to linked list of all threads + th->id = thread_id; + th->ready = 0; + th->arg = arg; + th->stack = Helios_Thread_GetStaskPtr(th->id); + + //stack_len must be 1/4 of ThreadAttr.stack_size + th->stack_len = ThreadAttr.stack_size / sizeof(uint32_t); + th->next = thread; + thread = th; + + // adjust the stack_size to provide room to recover from hitting the limit + *stack_size -= 1024; + + mp_thread_mutex_unlock(&thread_mutex); + + return (int)th;//return task_node +} + +//forrest.liu@20210408 increase the priority for that python thread can,t be scheduled +mp_uint_t mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) { + int th_node = mp_thread_create_ex(entry, arg, stack_size, (MP_THREAD_PRIORITY - 1), "mp_thread"); + return th_node; +} + +void mp_new_thread_add(uint32_t th_id, uint32_t stack_size) { + // Allocate linked-list node (must be outside thread_mutex lock) + thread_t *th = m_new_obj(thread_t); + // add thread to linked list of all threads + th->id = th_id; + th->ready = 0; + th->arg = NULL; + th->stack = Helios_Thread_GetStaskPtr((Helios_Thread_t)th->id); + + th->stack_len = stack_size / sizeof(uint32_t); + th->next = thread; + thread = th; +} + +void mp_thread_finish(void) { + mp_thread_mutex_lock(&thread_mutex, 1); + for (thread_t *th = thread; th != NULL; th = th->next) { + if (th->id == Helios_Thread_GetID()) { + th->ready = 0; + break; + } + } + mp_thread_mutex_unlock(&thread_mutex); +} + +bool mp_thread_finish_by_threadid(int thread_id) { + mp_thread_mutex_lock(&thread_mutex, 1); + for (thread_t *th = thread; th != NULL; th = th->next) { + if (th->id == (Helios_Thread_t)thread_id) { + th->ready = 0; + mp_thread_mutex_unlock(&thread_mutex); + return true; + } + } + mp_thread_mutex_unlock(&thread_mutex); + return false; +} + +bool mp_is_python_thread(void) { + Helios_Thread_t curr_id = Helios_Thread_GetID(); + mp_thread_mutex_lock(&thread_mutex, 1); + for (thread_t *th = thread; th != NULL; th = th->next) { + if (th->id == curr_id) { + mp_thread_mutex_unlock(&thread_mutex); + return true; + } + } + mp_thread_mutex_unlock(&thread_mutex); + return false; +} + +int mp_thread_get_current_tsknode(void) { + Helios_Thread_t curr_id = Helios_Thread_GetID(); + mp_thread_mutex_lock(&thread_mutex, 1); + for (thread_t *th = thread; th != NULL; th = th->next) { + if (th->id == (Helios_Thread_t)curr_id) { + mp_thread_mutex_unlock(&thread_mutex); + return (int)th; + } + } + mp_thread_mutex_unlock(&thread_mutex); + return 0; +} + +int mp_thread_get_tskid_by_tsknode(void *th_node) { + thread_t *th_id = (thread_t *)th_node; + mp_thread_mutex_lock(&thread_mutex, 1); + for (thread_t *th = thread; th != NULL; th = th->next) { + if (th == th_id) { + mp_thread_mutex_unlock(&thread_mutex); + return (int)th->id; + } + } + mp_thread_mutex_unlock(&thread_mutex); + return 0; +} + +mp_uint_t mp_thread_get_id(void) { + return (mp_uint_t)Helios_Thread_GetID(); +} + +void mp_thread_mutex_init(mp_thread_mutex_t *mutex) { + *mutex = Helios_Mutex_Create(); +} + +int mp_thread_mutex_lock(mp_thread_mutex_t *mutex, int wait) { + return Helios_Mutex_Lock(*mutex, wait ? QPY_WAIT_FOREVER : QPY_NO_WAIT); +} + +void mp_thread_mutex_unlock(mp_thread_mutex_t *mutex) { + Helios_Mutex_Unlock(*mutex); +} + +//Added by Freddy @20210818 delete a lock +void mp_thread_mutex_del(mp_thread_mutex_t *mutex) { + Helios_Mutex_Delete(*mutex); +} + +void mp_thread_semphore_init(mp_thread_semphore_t *sem, uint32_t initcount) { + *sem = Helios_Semaphore_Create(initcount, initcount); +} + +int mp_thread_semphore_acquire(mp_thread_semphore_t *sem, int wait) { + return Helios_Semaphore_Acquire(*sem, wait); +} + +void mp_thread_semphore_release(mp_thread_semphore_t *sem) { + Helios_Semaphore_Release(*sem); +} + +void mp_thread_semphore_del(mp_thread_semphore_t *sem) { + Helios_Semaphore_Delete(*sem); +} + +void mp_thread_deinit(void) { + for (;;) { + // Find a task to delete + int id = 0; + mp_thread_mutex_lock(&thread_mutex, 1); + for (thread_t *th = thread; th != NULL; th = th->next) { + // Don't delete the current task + if (th->id != Helios_Thread_GetID()) { + id = th->id; + break; + } + } + mp_thread_mutex_unlock(&thread_mutex); + + if (id == 0) { + // No tasks left to delete + break; + } else { + // Call qpy_thread_delete to delete the task (it will call vPortCleanUpTCB) + Helios_Thread_Delete(id); + _vPortCleanUpTCB((void*)id); + } + } +} + +unsigned int mp_get_available_memory_size(void) +{ + return Helios_GetAvailableMemorySize(); +} + + +#endif // MICROPY_PY_THREAD \ No newline at end of file diff --git a/ports/quectel/mpthreadport.h b/ports/quectel/mpthreadport.h new file mode 100644 index 0000000000000..2f36bf9c1f06a --- /dev/null +++ b/ports/quectel/mpthreadport.h @@ -0,0 +1,71 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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_MPTHREADPORT_H +#define MICROPY_INCLUDED_MPTHREADPORT_H + +#include "helios_os.h" + +#if defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) +#define MP_THREAD_MIN_STACK_SIZE (4 * 1024) +#define MP_THREAD_DEFAULT_STACK_SIZE (MP_THREAD_MIN_STACK_SIZE + 1024 + 1024) +#define MP_THREAD_PRIORITY 100 +#else +#define MP_THREAD_MIN_STACK_SIZE (32 * 1024) +#define MP_THREAD_DEFAULT_STACK_SIZE (MP_THREAD_MIN_STACK_SIZE + 1024) +#define MP_THREAD_PRIORITY 100 +#endif + + +typedef Helios_Mutex_t mp_thread_mutex_t; +typedef Helios_Sem_t mp_thread_semphore_t; + + +#define QPY_WAIT_FOREVER HELIOS_WAIT_FOREVER +#define QPY_NO_WAIT HELIOS_NO_WAIT + +void mp_thread_init(void *stack, uint32_t stack_len); +void mp_thread_gc_others(void); +void mp_thread_deinit(void); +unsigned int mp_get_available_memory_size(void); +bool mp_is_python_thread(void); +int mp_thread_get_current_tsknode(void); +int mp_thread_get_tskid_by_tsknode(void *th_node); + +void mp_thread_mutex_init(mp_thread_mutex_t *mutex); +int mp_thread_mutex_lock(mp_thread_mutex_t *mutex, int wait); +void mp_thread_mutex_unlock(mp_thread_mutex_t *mutex); +void mp_thread_mutex_del(mp_thread_mutex_t *mutex); + +void mp_thread_semphore_init(mp_thread_semphore_t *sem, uint32_t initcount); +int mp_thread_semphore_acquire(mp_thread_semphore_t *sem, int wait); +void mp_thread_semphore_release(mp_thread_semphore_t *sem); +void mp_thread_semphore_del(mp_thread_semphore_t *sem); + +void mp_new_thread_add(uint32_t th_id, uint32_t stack_size); + +#endif // MICROPY_INCLUDED_MPTHREADPORT_H + diff --git a/ports/quectel/plat.mk b/ports/quectel/plat.mk new file mode 100644 index 0000000000000..48c748053e4b2 --- /dev/null +++ b/ports/quectel/plat.mk @@ -0,0 +1,9 @@ +# plat definition + +ifeq ($(strip $(PLAT)),) +export PLAT = Unisoc +export BOARD = EG915UEC_AC + +DFLAGS = PLAT_$(strip $(PLAT)) BOARD_$(strip $(BOARD)) BOARD=$(strip $(BOARD)) +endif + diff --git a/ports/quectel/qstrdefsport.h b/ports/quectel/qstrdefsport.h new file mode 100644 index 0000000000000..00d3e2ae3c555 --- /dev/null +++ b/ports/quectel/qstrdefsport.h @@ -0,0 +1,2 @@ +// qstrs specific to this port +// *FORMAT-OFF* diff --git a/ports/quectel/quectel.mk b/ports/quectel/quectel.mk new file mode 100644 index 0000000000000..a788f43a006f2 --- /dev/null +++ b/ports/quectel/quectel.mk @@ -0,0 +1,422 @@ +include plat.mk + +PLAT_DFLAGS = $(addprefix -D,$(DFLAGS)) +PLAT_CFLAGS = $(QUEC_CFLAGS) +PLAT_CFLAGS += -Wno-unused-parameter -Wformat=0 -Wno-unused-function + +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/config +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/include + +ifeq ($(strip $(PLAT)),Qualcomm) +INC += -I$(COMPILER_PATH)/armv7m-none-eabi/libc/include +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/c-utility +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/c-utility/inc +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/c-utility/inc/azure_c_shared_utility +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/c-utility/pal +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/c-utility/pal/generic +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/iothub_client +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/iothub_client/inc +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/iothub_client/inc/internal +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/serializer +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/serializer/inc +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/umqtt +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/umqtt/inc +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/umqtt/inc/azure_umqtt_c +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/qapi +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/threadx_api +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include +INC += -I$(ROOT)/system/at +INC += -I$(ROOT)/system/esim +endif + +INC += -I. +INC += -I$(HEADER_BUILD) +INC += -I$(TOP) +INC += -I$(TOP)/py +INC += -I$(TOP)/extmod +INC += -I$(TOP)/lib/utils +INC += -I$(TOP)/lib/mp-readline +INC += -I$(TOP)/lib/littlefs +INC += -I$(TOP)/lib/netutils +INC += -I$(TOP)/lib/timeutils +INC += -I$(ROOT)/peripheral +INC += -I$(ROOT)/system/include +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/include +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include +INC += -I$(ROOT)/system/debug +INC += -I$(ROOT)/system/dev +INC += -I$(ROOT)/system/fs +INC += -I$(ROOT)/system/hal +INC += -I$(ROOT)/system/gnss +INC += -I$(ROOT)/system/network +INC += -I$(ROOT)/system/at +INC += -I$(ROOT)/system/aliiot + +ifeq ($(strip $(PLAT)),$(filter $(PLAT),ASR_1803s ASR_1803sc)) +INC += -I$(ROOT)/system/csd +INC += -I$(ROOT)/system/esim +endif +ifeq ($(strip $(PLAT)),ASR_1606) +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include +endif +ifeq ($(strip $(PLAT)),ASR_1602) +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include +endif +ifeq ($(strip $(PLAT)),ASR_1609) +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include +endif + +ifeq ($(strip $(PLAT)),Unisoc) +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT)) +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/apps +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/priv +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/prot +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/netif +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix/arpa +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix/net +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix/netinet +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix/sys +INC += -I$(ROOT)/system/at +INC += -I$(ROOT)/system/esim +endif + +ifeq ($(strip $(PLAT)),$(filter $(PLAT),Unisoc_8910_R05 Unisoc_8910_R06)) +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT)) +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/apps +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/priv +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/prot +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/netif +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/netif/ppp +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/netif/ppp/polarssl +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix/arpa +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix/net +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix/netinet +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix/sys +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/stdc +INC += -I$(ROOT)/system/esim +endif + +ifeq ($(strip $(PLAT)),$(filter $(PLAT),EIGEN EIGEN_718)) +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT)) +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/lwip +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/lwip/apps +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/lwip/priv +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/lwip/prot +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/arch +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/netif +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/posix +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/posix/sys +endif + +ifeq ($(strip $(PLAT)),$(filter $(PLAT),SONY_ALT1350)) +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT)) +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/arch +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/lwip +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/lwip/priv +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/lwip/prot +endif + +ifeq ($(strip $(PLAT)),$(filter $(PLAT),Unisoc_8850 Unisoc_8850_R02)) +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT)) +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/apps +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/priv +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/prot +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/netif +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/netif/ppp +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/netif/ppp/polarssl +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix/arpa +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix/net +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix/netinet +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix/sys +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/stdc +endif + +ifeq ($(strip $(PLAT)),RDA) +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT)) +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/arch +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/apps +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/priv +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/prot +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/netif +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix/arpa +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix/net +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix/netinet +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix/sys +endif + +ifeq ($(strip $(PLAT)), $(filter $(PLAT),ASR ASR_1803s ASR_1803sc)) +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT)) +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include +INC += -I$(ROOT)/system/at +endif + +ifeq ($(strip $(PLAT)),ECR6600) +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT)) +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include +endif + +ifeq ($(strip $(PLAT)),aic8800m40) +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/lwip-STABLE-2_0_2_RELEASE_VER/ports/rtos/include +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/lwip-STABLE-2_0_2_RELEASE_VER/ports/rtos/include/arch +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/lwip-STABLE-2_0_2_RELEASE_VER/src/include +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/lwip-STABLE-2_0_2_RELEASE_VER/src/include/lwip +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/lwip-STABLE-2_0_2_RELEASE_VER/src/include/lwip/priv +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/lwip-STABLE-2_0_2_RELEASE_VER/src/include/lwip/prot +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/lwip-STABLE-2_0_2_RELEASE_VER/src/include/netif +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/lwip-STABLE-2_0_2_RELEASE_VER/src/include/posix +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/lwip-STABLE-2_0_2_RELEASE_VER/src/include/posix/sys +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/net_al +endif + +#ifeq ($(CONFIG_MBEDTLS), 1) +INC += -I$(ROOT)/system/mbedtls +INC += -I$(ROOT)/system/mbedtls/include +INC += -I$(ROOT)/system/mbedtls/include/mbedtls +INC += -I$(ROOT)/system/mbedtls/library +INC += -I$(ROOT)/system/mbedtls/port/helios/inc +#endif + +INC += -I$(ROOT)/system/network +INC += -I$(ROOT)/system/os +INC += -I$(ROOT)/system/startup +INC += -I$(ROOT)/system/fota +INC += -I$(ROOT)/system/bt +INC += -I$(ROOT)/system/at +ifeq (y, $(CONFIG_LVGL)) +INC += -I$(TOP)/lib/lvgl +INC += -I$(TOP)/lib/lvgl/src +INC += -I$(TOP)/lib/lvgl/src/core +INC += -I$(TOP)/lib/lvgl/src/draw +INC += -I$(TOP)/lib/lvgl/src/extra +INC += -I$(TOP)/lib/lvgl/src/font +INC += -I$(TOP)/lib/lvgl/src/gpu +INC += -I$(TOP)/lib/lvgl/src/hal +INC += -I$(TOP)/lib/lvgl/src/misc +INC += -I$(TOP)/lib/lvgl/src/widgts +endif +INC += -I$(ROOT)/driver +INC += -I$(ROOT)/driver/lcd +ifeq (y, $(CONFIG_QRCODE)) +INC += -I$(ROOT)/components/qrcode +endif +ifeq ($(CONFIG_JRTC), y) +INC += -I$(ROOT)/components/jrtc/inc +endif + +ifeq ($(CONFIG_SENSOR_VC9202), y) +INC += -I$(ROOT)/components/sensor/VC9202/inc +INC += -I$(ROOT)/components/sensor/VC9202/algo/inc +endif + +ifeq (y, $(CONFIG_QUECTHING)) +INC += -I$(ROOT)/components/quecsdk/cloud +INC += -I$(ROOT)/components/quecsdk/driverLayer +INC += -I$(ROOT)/components/quecsdk/thirdLib/mqtt +INC += -I$(ROOT)/components/quecsdk/thirdLib/cJSON +INC += -I$(ROOT)/components/quecsdk/kernel +endif +ifeq ($(CONFIG_SPINAND), y) +INC += -I$(ROOT)/components/fs/include +INC += -I$(ROOT)/components/fs/yaffs/src/direct +INC += -I$(ROOT)/components/fs/yaffs/src/port +INC += -I$(ROOT)/components/fs/yaffs/src +INC += -I$(ROOT)/components/fs/yaffs +endif +ifeq ($(CONFIG_RTMP), y) +INC += -I$(ROOT)/components/rtmpdump/librtmp/inc +INC += -I$(ROOT)/components/rtmpdump/libz/inc +endif +INC += -I$(ROOT)/utilities +ifeq ($(CONFIG_JPEG), y) +INC += -I$(ROOT)/components/libjpeg-turbo/include +INC += -I$(ROOT)/components/libjpeg-turbo +INC += -I$(ROOT)/components/libjpeg-turbo/src +INC += -I$(ROOT)/components/libjpeg-turbo/src/simd +endif +ifeq ($(CONFIG_POC_BND), y) +INC += -I$(ROOT)/components/poc +INC += -I$(ROOT)/components/poc/bnd/inc +endif +ifeq ($(CONFIG_POC_BND_XIN), y) +INC += -I$(ROOT)/components/poc +INC += -I$(ROOT)/components/poc/bnd_xin/inc +endif +ifeq ($(CONFIG_POC_SL), y) +INC += -I$(ROOT)/components/poc +INC += -I$(ROOT)/components/poc/sl/inc +endif +ifeq ($(CONFIG_POC_QS), y) +INC += -I$(ROOT)/components/poc +INC += -I$(ROOT)/components/poc/qs/inc +endif +#Carlos.Meng add 2024/02/22 +ifeq ($(CONFIG_POC_QS_R07), y) +INC += -I$(ROOT)/components/poc +INC += -I$(ROOT)/components/poc/qs/inc +endif +#Stephen.Gao add 2022/11/23 +ifeq ($(CONFIG_POC_ZZD), y) +INC += -I$(ROOT)/components/poc +INC += -I$(ROOT)/components/poc/zzd/inc +endif +#Stephen.Gao add 2023/01/06 +ifeq ($(CONFIG_POC_YDWL), y) +INC += -I$(ROOT)/components/poc +INC += -I$(ROOT)/components/poc/ydwl/inc +endif + +ifeq ($(CONFIG_POC_SLPOC), y) +INC += -I$(ROOT)/components/poc -I$(ROOT)/components/poc/slpoc/src +INC += -I$(ROOT)/components/poc/slpoc/inc +SRC_QSTR += $(ROOT)/components/poc/slpoc/src/modpoc_slpoc.c +endif + +ifeq ($(CONFIG_POC_RDA_BND), y) +INC += -I$(ROOT)/components/poc -I$(ROOT)/components/poc/rda_bnd/src +INC += -I$(ROOT)/components/poc/rda_bnd/inc +SRC_QSTR += $(ROOT)/components/poc/rda_bnd/src/modpocrda.c +endif + +ifeq ($(CONFIG_POC_RDA_BND_XIN), y) +INC += -I$(ROOT)/components/poc -I$(ROOT)/components/poc/rda_bnd_xin/src +INC += -I$(ROOT)/components/poc/rda_bnd_xin/inc +SRC_QSTR += $(ROOT)/components/poc/rda_bnd_xin/src/modpocrda.c +endif + +ifeq ($(CONFIG_POC_TID), y) +INC += -I$(ROOT)/components/poc -I$(ROOT)/components/poc/tid/src +INC += -I$(ROOT)/components/poc/tid/inc +SRC_QSTR += $(ROOT)/components/poc/tid/src/modpoc_tid.c +endif + +ifeq (y,$(CONFIG_DECODE_ZBAR)) +INC += -I$(ROOT)/components/decode/ZBar/zbar +INC += -I$(ROOT)/components/decode/ZBar/include +INC += -I$(ROOT)/components/decode/ZBar/zbar/decoder +INC += -I$(ROOT)/components/decode/ZBar/zbar/qrcode +endif +ifeq (y,$(CONFIG_DECODE_QUECTEL)) +INC += -I$(ROOT)/components/decode/quectel/inc +endif + +ifeq (y,$(CONFIG_DECODE_QINGYA)) +ifneq ($(strip $(PLAT)),ASR) +ifneq ($(strip $(PLAT)),ASR_1606) +INC += -I$(ROOT)/components/decode/qingya +endif +endif +endif + +ifeq ($(CONFIG_SPI_SDCARD), y) +INC += -I$(ROOT)/components/fs/fatfs/include +endif + +ifeq ($(CONFIG_AUDIO_G711_COMPRESS), y) +INC += -I$(ROOT)/components/audio/G711 +endif +ifeq ($(strip $(PLAT)),EIGEN) +INC += -I$(ROOT)/components/audio +endif + +ifeq ($(CONFIG_GMSSL), y) +INC += -I$(ROOT)/components/GMSSL/include +INC += -I$(ROOT)/components/GMSSL/include/gmssl +endif + +ifeq ($(CONFIG_GB2312), y) +INC += -I$(ROOT)/components/decode/gb2312 +endif + +ifeq ($(CONFIG_ESIMSDK), y) +INC += -I$(ROOT)/components/esim/inc +endif + +ifeq ($(CONFIG_ESIM_IPA), y) +INC += -I$(ROOT)/system/esim +endif + +ifeq ($(CONFIG_AUDIO_G729_COMPRESS), y) +INC += -I$(ROOT)/components/audio/G729 +INC += -I$(ROOT)/components/audio/G729/src +INC += -I$(ROOT)/components/audio/G729/include +endif + +ifeq ($(CONFIG_NFC_SL6320), y) +INC += -I$(ROOT)/components/NFC/SL6320 +endif + +ifeq ($(CONFIG_VOIP), y) +INC += -I$(ROOT)/components/voip/libexosip2/include +INC += -I$(ROOT)/components/voip/libosip2/include +INC += -I$(ROOT)/components/voip/rtp +endif + +ifeq ($(CONFIG_ETHERNET_W5500), y) +INC += -I$(ROOT)/components/ethernet/wiznet +endif + +ifeq ($(CONFIG_SLIP), y) +INC += -I$(ROOT)/components/slip +endif + +ifeq ($(MICROPY_VFS_QUECFS),1) +QUEC_MOD_CFLAGS += -DMICROPY_VFS_QUECFS=1 +endif + +QUEC_SRC += \ + main.c \ + mphalport.c \ + mpthreadport.c \ + help.c + +# modules source file will used by gen +QUEC_SRC_MOD += \ + gccollect.c \ + moduos.c \ + modutime.c \ + modsocket.c \ + modostimer.c \ + modfota.c \ + callbackdeal.c \ + modmachine.c \ + machine_pin.c \ + machine_wdt.c \ + machine_rtc.c \ + machine_uart.c \ + machine_timer.c \ + moddev.c \ + misc_power.c \ + modmisc.c \ + misc_usbnet.c \ + modsim.c \ + modnet.c \ + moddatacall.c \ + machine_extint.c \ + misc_adc.c \ + misc_pwm.c \ + modexample.c \ + machine_iic.c \ + machine_hw_spi.c \ + utime_mphal.c \ + modflashdev.c \ + modussl_mbedtls.c \ + modhelios.c diff --git a/ports/quectel/utime_mphal.c b/ports/quectel/utime_mphal.c new file mode 100644 index 0000000000000..a208971ee50e5 --- /dev/null +++ b/ports/quectel/utime_mphal.c @@ -0,0 +1,110 @@ +/* + * 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 + * Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. + * + * 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 "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_TIME_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_TIME_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_TIME_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_get_int_truncated(start_in); + mp_uint_t end = mp_obj_get_int_truncated(end_in); + //mp_obj_get_int_truncated + // 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_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_TIME_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/ports/quectel/utime_mphal.h b/ports/quectel/utime_mphal.h new file mode 100644 index 0000000000000..5bb1d493b1fcd --- /dev/null +++ b/ports/quectel/utime_mphal.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 + * Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. + * + * 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 From d187692a49baa38bd364c4fdb6a375c0a2620fac Mon Sep 17 00:00:00 2001 From: Nikola Neskovic Date: Wed, 4 Mar 2026 14:59:00 +0100 Subject: [PATCH 02/13] ports/quectel: Update to minimal port. --- ports/quectel/Makefile | 71 +- ports/quectel/callbackdeal.c | 885 ------- ports/quectel/callbackdeal.h | 389 ---- ports/quectel/machine_extint.c | 734 ------ ports/quectel/machine_hw_spi.c | 265 --- ports/quectel/machine_i2c.h | 90 - ports/quectel/machine_iic.c | 188 -- ports/quectel/machine_pin.c | 333 --- ports/quectel/machine_rtc.c | 228 -- ports/quectel/machine_timer.c | 311 --- ports/quectel/machine_uart.c | 492 ---- ports/quectel/machine_wdt.c | 101 - ports/quectel/main.c | 21 - ports/quectel/misc_adc.c | 119 - ports/quectel/misc_power.c | 107 - ports/quectel/misc_pwm.c | 390 ---- ports/quectel/misc_usbnet.c | 213 -- ports/quectel/moddatacall.c | 833 ------- ports/quectel/moddatacall.h | 42 - ports/quectel/moddev.c | 288 --- ports/quectel/modexample.c | 127 - ports/quectel/modfota.c | 446 ---- ports/quectel/modmachine.c | 113 - ports/quectel/modmachine.h | 53 - ports/quectel/modmisc.c | 253 -- ports/quectel/modmisc.h | 48 - ports/quectel/modnet.c | 2423 -------------------- ports/quectel/modostimer.c | 167 -- ports/quectel/modsim.c | 1128 --------- ports/quectel/modsim.h | 222 -- ports/quectel/modsocket.c | 1280 ----------- ports/quectel/modules/_boot.py | 96 +- ports/quectel/modules/app_fota.py | 33 - ports/quectel/modules/app_fota_download.py | 212 -- ports/quectel/modules/app_fota_mount.py | 49 - ports/quectel/modules/app_fota_updater.py | 91 - ports/quectel/modules/checkNet.py | 231 -- ports/quectel/modules/checksum.py | 157 -- ports/quectel/modules/dataCall.py | 284 --- ports/quectel/modules/file_crc32.py | 45 - ports/quectel/modules/log.py | 119 - ports/quectel/modules/modules.py | 1 + ports/quectel/modules/ql_fs.py | 137 -- ports/quectel/modules/queue.py | 51 - ports/quectel/modules/request.py | 470 ---- ports/quectel/modules/umqtt.py | 776 ------- ports/quectel/moduos.c | 14 - ports/quectel/modussl_mbedtls.c | 600 ----- ports/quectel/modutime.c | 220 -- ports/quectel/mpconfigport.h | 42 +- ports/quectel/mpconfigport.mk | 32 +- ports/quectel/mphalport.c | 34 - ports/quectel/mphalport.h | 25 +- ports/quectel/mpthreadport.c | 3 +- ports/quectel/mpthreadport.h | 1 - ports/quectel/quectel.mk | 354 +-- ports/quectel/utime_mphal.c | 110 - ports/quectel/utime_mphal.h | 43 - 58 files changed, 42 insertions(+), 16548 deletions(-) delete mode 100644 ports/quectel/callbackdeal.c delete mode 100644 ports/quectel/callbackdeal.h delete mode 100644 ports/quectel/machine_extint.c delete mode 100644 ports/quectel/machine_hw_spi.c delete mode 100644 ports/quectel/machine_i2c.h delete mode 100644 ports/quectel/machine_iic.c delete mode 100644 ports/quectel/machine_pin.c delete mode 100644 ports/quectel/machine_rtc.c delete mode 100644 ports/quectel/machine_timer.c delete mode 100644 ports/quectel/machine_uart.c delete mode 100644 ports/quectel/machine_wdt.c delete mode 100644 ports/quectel/misc_adc.c delete mode 100644 ports/quectel/misc_power.c delete mode 100644 ports/quectel/misc_pwm.c delete mode 100644 ports/quectel/misc_usbnet.c delete mode 100644 ports/quectel/moddatacall.c delete mode 100644 ports/quectel/moddatacall.h delete mode 100644 ports/quectel/moddev.c delete mode 100644 ports/quectel/modexample.c delete mode 100644 ports/quectel/modfota.c delete mode 100644 ports/quectel/modmachine.c delete mode 100644 ports/quectel/modmachine.h delete mode 100644 ports/quectel/modmisc.c delete mode 100644 ports/quectel/modmisc.h delete mode 100644 ports/quectel/modnet.c delete mode 100644 ports/quectel/modostimer.c delete mode 100644 ports/quectel/modsim.c delete mode 100644 ports/quectel/modsim.h delete mode 100644 ports/quectel/modsocket.c delete mode 100644 ports/quectel/modules/app_fota.py delete mode 100644 ports/quectel/modules/app_fota_download.py delete mode 100644 ports/quectel/modules/app_fota_mount.py delete mode 100644 ports/quectel/modules/app_fota_updater.py delete mode 100644 ports/quectel/modules/checkNet.py delete mode 100644 ports/quectel/modules/checksum.py delete mode 100644 ports/quectel/modules/dataCall.py delete mode 100644 ports/quectel/modules/file_crc32.py delete mode 100644 ports/quectel/modules/log.py create mode 100644 ports/quectel/modules/modules.py delete mode 100644 ports/quectel/modules/ql_fs.py delete mode 100644 ports/quectel/modules/queue.py delete mode 100644 ports/quectel/modules/request.py delete mode 100644 ports/quectel/modules/umqtt.py delete mode 100644 ports/quectel/modussl_mbedtls.c delete mode 100644 ports/quectel/modutime.c delete mode 100644 ports/quectel/utime_mphal.c delete mode 100644 ports/quectel/utime_mphal.h diff --git a/ports/quectel/Makefile b/ports/quectel/Makefile index 39f6f6dbcfe1e..eed5684fb46ee 100644 --- a/ports/quectel/Makefile +++ b/ports/quectel/Makefile @@ -5,64 +5,16 @@ include ../../py/mkenv.mk include mpconfigport.mk include quectel.mk -include ../../py/verbose.mk +CROSS = 1 -# 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:/=)) +ifeq ($(CROSS), 1) +CFLAGS = $(INC) $(QUEC_MOD_CFLAGS) $(PLAT_CFLAGS) $(PLAT_DFLAGS) $(COPT) else -# If not given on the command line, then default to RPI_PICO. -BOARD ?= EC600UCN_LB -BOARD_DIR ?= boards/$(BOARD) +LD = gcc +CFLAGS = $(INC) -Wall -Werror -Wdouble-promotion -Wfloat-conversion -std=c99 $(COPT) +LDFLAGS = -Wl,-Map=$@.map,--cref -Wl,--gc-sections endif -ifeq ($(wildcard $(BOARD_DIR)/.),) -ifeq ($(findstring boards/PICO,$(BOARD_DIR)),boards/PICO) -$(warning The PICO* boards have been renamed to RPI_PICO*) -endif -$(error Invalid BOARD specified: $(BOARD_DIR)) -endif - -# If the build directory is not given, make it reflect the board name (and -# optionally the board variant). -ifneq ($(BOARD_VARIANT),) -BUILD ?= build-$(BOARD)-$(BOARD_VARIANT) -else -BUILD ?= build-$(BOARD) -endif - -ifeq ($(BUILD_VERBOSE),1) -MAKE_ARGS += VERBOSE=1 # Picked up in Makefile generated by CMake -endif - -MAKE_ARGS += -DMICROPY_BOARD=$(BOARD) -DMICROPY_BOARD_DIR="$(abspath $(BOARD_DIR))" - -ifdef USER_C_MODULES -MAKE_ARGS += -DUSER_C_MODULES=${USER_C_MODULES} -endif - -ifneq ($(FROZEN_MANIFEST),) -MAKE_ARGS += -DMICROPY_FROZEN_MANIFEST=${FROZEN_MANIFEST} -endif - -ifeq ($(DEBUG),1) -MAKE_ARGS += -DCMAKE_BUILD_TYPE=Debug -endif - -ifdef BOARD_VARIANT -MAKE_ARGS += -DMICROPY_BOARD_VARIANT=$(BOARD_VARIANT) -endif - -ifdef MICROPY_PREVIEW_VERSION_2 -MAKE_ARGS += -DMICROPY_PREVIEW_VERSION_2=1 -endif - -FROZEN_MANIFEST ?= boards/manifest.py - -CFLAGS = $(INC) $(QUEC_MOD_CFLAGS) $(PLAT_CFLAGS) $(PLAT_DFLAGS) $(COPT) $(MAKE_ARGS) - CSUPEROPT = -Os # save some code space # qstr definitions (must come before including py.mk) @@ -71,12 +23,17 @@ QSTR_DEFS = qstrdefsport.h # MicroPython feature configurations MICROPY_ROM_TEXT_COMPRESSION ?= 1 + +FROZEN_MANIFEST = $(QUEC_PY_MOD) + +export MICROPY_MPYCROSS = $(TOP)/mpy-cross/build/mpy-cross.exe # include py core make definitions include $(TOP)/py/py.mk include $(TOP)/extmod/extmod.mk +ifeq ($(CROSS), 1) CROSS_COMPILE ?= arm-none-eabi- - +endif INC += -I. INC += -I$(TOP) @@ -139,7 +96,11 @@ SRC_QSTR += $(SRC_MOD) $(SRC_MOD_CXX) $(SHARED_SRC_C) $(EXTMOD_SRC_C) OBJ += $(PY_CORE_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_CXX:.cpp=.o)) +ifeq ($(CROSS), 1) all: $(BUILD)/firmware.a +else +all: $(BUILD)/firmware.elf +endif $(BUILD)/_frozen_mpy.c: frozentest.mpy $(BUILD)/genhdr/qstrdefs.generated.h $(ECHO) "MISC freezing bytecode" diff --git a/ports/quectel/callbackdeal.c b/ports/quectel/callbackdeal.c deleted file mode 100644 index dce7dcd77dc4a..0000000000000 --- a/ports/quectel/callbackdeal.c +++ /dev/null @@ -1,885 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020-2021 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 "helios_os.h" -#include "stackctrl.h" -#include "py/runtime.h" -#include "py/gc.h" -#include "callbackdeal.h" -#include "py/obj.h" -#if MICROPY_ENABLE_CALLBACK_DEAL - - -#ifdef QPY_CALLBACKDEAL_LOG_ENABLE -#if defined(PLAT_ASR) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_ASR_1602) -extern void ql_log_mask_set(unsigned long long module_mask, unsigned int port_mask); -extern void _ql_app_log(const char* fmt, ...); -static char usb_trace_init_flag = 0; -#define qpy_callbackdeal_trace(fmt, ...) do{ \ - if(!usb_trace_init_flag) \ - { \ - ql_log_mask_set(0x20, 0x02); \ - usb_trace_init_flag = 1; \ - } \ - _ql_app_log("[%s][%s, L%d]"fmt"", "cbdl", __FUNCTION__, __LINE__, ##__VA_ARGS__); \ - }while(0) - -#elif defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_Unisoc_8850_R02) || defined(PLAT_Unisoc_8910_R06) -#include "helios_debug.h" -#define qpy_callbackdeal_trace(fmt, ...) Helios_Debug_Output("[%s][%s, L%d]"fmt"", "cbdl", __FUNCTION__, __LINE__, ##__VA_ARGS__) -#else -#error "The platform not support usb trace!!!" -#endif -#else -#define qpy_callbackdeal_trace(fmt, ...) -#endif - - - -#define QPY_CALLBACK_DEAL_MSG_MAX_NUM (2 * MICROPY_SCHEDULER_DEPTH) -#if defined(PLAT_ECR6600) || defined (PLAT_aic8800m40) -#define QPY_CALLBACK_DEAL_THREAD_STACK_SIZE (4 *1024) -#else -#define QPY_CALLBACK_DEAL_THREAD_STACK_SIZE (16 *1024) -#endif - -static Helios_MsgQ_t qpy_callback_deal_queue = 0; -Helios_Thread_t qpy_callback_deal_task_ref = 0; - -typedef struct _callback_deal_thread_entry_args_t { - mp_obj_dict_t *dict_locals; - mp_obj_dict_t *dict_globals; -} callback_deal_thread_entry_args_t; - -#if MICROPY_QPY_MODULE_BT -extern void qpy_bt_msg_proc(void *msg); -#endif -#if MICROPY_QPY_MODULE_BLE -extern void qpy_ble_msg_proc(void *msg); -#endif - -#if MICROPY_QPY_MODULE_POC -extern void qpy_poc_msg_proc ( void *msg ); -#endif //end MICROPY_QPY_MODULE_POC - -#if MICROPY_QPY_MODULE_LWM2M -extern void qpy_lwm2m_msg_proc(void *param); -#endif //end MICROPY_QPY_MODULE_LWM2M - -#if MICROPY_QPY_MODULE_ESIM && MICROPY_QPY_MODULE_ESIM_IPA -extern void qpy_esim_msg_proc(void *param); -#endif -/* - * Create a task&queue that handles callback tasks exclusively - */ -void qpy_callback_deal_thread(void * args_in); - -/*Jayceon 2022/08/31 add for QuecPython --start*/ -extern bool mp_obj_is_boundmeth(mp_obj_t o); -extern mp_obj_t mp_obj_bound_get_self(void *bound); -extern mp_obj_t mp_obj_bound_get_meth(void *bound); -extern bool mp_obj_is_closure(void *obj); -extern mp_obj_t mp_obj_closure_get_fun(void *closure); - -typedef struct temp_mp_obj_bound_meth_t { - mp_obj_base_t base; - mp_obj_t meth; - mp_obj_t self; -} temp_mp_obj_bound_meth_t; - -typedef struct temp_mp_obj_closure_t { - mp_obj_base_t base; - mp_obj_t fun; - size_t n_closed; - mp_obj_t closed[]; -} temp_mp_obj_closure_t; - -mp_obj_t mp_obj_bound_get_self(void *bound) -{ - if(NULL == bound) - return NULL; - - return ((temp_mp_obj_bound_meth_t *)bound)->self; -} - -mp_obj_t mp_obj_bound_get_meth(void *bound) -{ - if(NULL == bound) - return NULL; - - return ((temp_mp_obj_bound_meth_t *)bound)->meth; -} - -bool mp_obj_is_boundmeth(mp_obj_t o) { - - return mp_obj_is_type(o, &mp_type_bound_meth); -} - -extern const mp_obj_type_t mp_type_closure; -bool mp_obj_is_closure(void *obj) -{ - return mp_obj_is_type(obj, &mp_type_closure); -} - -mp_obj_t mp_obj_closure_get_fun(void *closure){ - if(NULL == closure) - return NULL; - - return ((temp_mp_obj_closure_t *)closure)->fun; -} - -extern void mp_main_thread_wakeup(); -static bool _mp_sched_schedule_ex(c_callback_t *callback) { - - // When executing code within a handler we must lock the scheduler to - // prevent any scheduled callbacks from running, and lock the GC to - // prevent any memory allocations. - mp_sched_lock(); - gc_lock(); - nlr_buf_t nlr; - if (nlr_push(&nlr) == 0) { - mp_sched_schedule(callback->cb, callback->arg); - nlr_pop(); - } else { - // Uncaught exception; disable the callback so that it doesn't run again - mp_printf(&mp_plat_print, "Uncaught exception in IRQ callback handler\n"); - mp_obj_print_exception(MICROPY_ERROR_PRINTER, MP_OBJ_FROM_PTR(nlr.ret_val)); - gc_unlock(); - mp_sched_unlock(); - return false; - } - gc_unlock(); - mp_sched_unlock(); - - mp_main_thread_wakeup(); - return true; -} - -//Add a callback to the unscheduled table. If it is a Method, -//load it first so that the recorded callback is not collected by the GC -bool mp_sched_schedule_ex(c_callback_t *callback, mp_obj_t arg) -{ - (void)arg; - if(NULL == callback) - { - return false; - } - - if((false == callback->is_method) && mp_obj_is_callable(callback->cb))//function - { - return _mp_sched_schedule_ex(callback); - } - else if(true == callback->is_method)//bound_method - { - if(mp_obj_is_boundmeth(callback->cb)) { - return _mp_sched_schedule_ex(callback); - } else { - mp_obj_t cb = mp_load_attr(callback->method_self, callback->method_name); - callback->cb = cb;//record a new boundmeth - return _mp_sched_schedule_ex(callback); - } - } - else - { - return false; - } -} - -//Register callback -bool mp_sched_schedule_callback_register(c_callback_t *callback, mp_obj_t func_obj) -{ - if(NULL == callback || NULL == func_obj) { - return false; - } - //memset(callback, 0 , sizeof(c_callback_t)); - if(mp_const_none != func_obj) - { - if(mp_obj_is_boundmeth(func_obj))//is bound_meth. Records the object for this method, along with the bytecode for the name of this method - { - callback->is_method = true; - callback->method_self = mp_obj_bound_get_self(func_obj); - mp_obj_t fun = mp_obj_bound_get_meth((int*)func_obj); - if(mp_obj_is_closure(fun)) { - callback->method_name = mp_obj_fun_get_name(mp_obj_closure_get_fun(fun)); - } else { - callback->method_name = mp_obj_fun_get_name(fun); - } - callback->cb = func_obj; - return true; - } - } - - callback->is_method = false; - callback->cb = func_obj; - - return true; -} - -void qpy_callback_deal_init(void) -{ -#if !defined(PLAT_RDA) - qpy_callback_deal_queue = Helios_MsgQ_Create(QPY_CALLBACK_DEAL_MSG_MAX_NUM, sizeof(st_CallBack_Deal)); -#endif - // create thread - callback_deal_thread_entry_args_t *th_args; - th_args = m_new_obj(callback_deal_thread_entry_args_t); - // pass our locals and globals into the new thread - th_args->dict_locals = mp_locals_get(); - th_args->dict_globals = mp_globals_get(); - - Helios_ThreadAttr ThreadAttr = { - .name = "cb_deal", - .stack_size = QPY_CALLBACK_DEAL_THREAD_STACK_SIZE, - .priority = (MP_THREAD_PRIORITY - 2),//high than mpthread - .entry = (void*)qpy_callback_deal_thread, - .argv = (void*)th_args - }; - qpy_callback_deal_task_ref = Helios_Thread_Create(&ThreadAttr); - //add thread to python_thread link list, the thread is automatically deleted after the VM restarts. - mp_new_thread_add((uint32_t)qpy_callback_deal_task_ref, QPY_CALLBACK_DEAL_THREAD_STACK_SIZE); -} - -/* - * Returns whether the current thread is callbackdeal thread - */ -bool qpy_is_callback_deal_thread(void) -{ - return (Helios_Thread_GetID() == qpy_callback_deal_task_ref); -} - -/* - * delete callback_deal task&queue - */ -void qpy_callback_deal_deinit(void) -{ - Helios_MsgQ_Delete(qpy_callback_deal_queue); qpy_callback_deal_queue = (Helios_MsgQ_t)0; - //Just set it to null and the thread will be deleted automatically when the vm restarts - qpy_callback_deal_task_ref = (Helios_Thread_t)0; -} - - -//Added by Freddy @20211124 发送消息至deal task的queue -int qpy_send_msg_to_callback_deal_thread(uint8_t id, void *msg) -{ - int ret = -1; - if((Helios_MsgQ_t)0 != qpy_callback_deal_queue) - { - st_CallBack_Deal cb_msg = {0}; - cb_msg.callback_type_id = id; - cb_msg.msg = msg; - qpy_callbackdeal_trace("callback_type_id:%d", id); - ret = Helios_MsgQ_Put(qpy_callback_deal_queue, (void*)(&cb_msg), sizeof(st_CallBack_Deal), HELIOS_NO_WAIT); - } - return ret; -} - - -st_CallBack_LoadBoundMeth * qpy_callback_para_node_add(c_callback_t *callback, mp_obj_t arg) -{ - st_CallBack_LoadBoundMeth *loadboundmet_msg = calloc(1, sizeof(st_CallBack_LoadBoundMeth)); - if(NULL == loadboundmet_msg) - { - return NULL; - } -#if defined(PLAT_ASR) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_ASR_1602) - int rc = Helios_Critical_Enter(); -#endif - loadboundmet_msg->next = (st_CallBack_LoadBoundMeth *)MP_STATE_PORT(loadmeth_para); - loadboundmet_msg->callback = callback; - loadboundmet_msg->arg = arg; - MP_STATE_PORT(loadmeth_para) = (void *)loadboundmet_msg; - qpy_callbackdeal_trace("loadmeth_para:0x%x", MP_STATE_PORT(loadmeth_para)); -#if defined(PLAT_ASR) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_ASR_1602) - Helios_Critical_Exit(rc); -#endif - - return loadboundmet_msg; -} - - -void qpy_callback_para_node_delete(st_CallBack_LoadBoundMeth *cb_msg) -{ -#if defined(PLAT_ASR) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_ASR_1602) - int rc = Helios_Critical_Enter(); -#endif - qpy_callbackdeal_trace("loadmeth_para:0x%x", MP_STATE_PORT(loadmeth_para)); - st_CallBack_LoadBoundMeth *loadmeth_para_head = (st_CallBack_LoadBoundMeth *)MP_STATE_PORT(loadmeth_para); - st_CallBack_LoadBoundMeth *loadmeth_para_tmp = loadmeth_para_head; - for(;loadmeth_para_head != NULL; loadmeth_para_head = loadmeth_para_head->next) - { - if(loadmeth_para_head == cb_msg) - { - qpy_callbackdeal_trace("cb_msg:0x%x", cb_msg); - if(loadmeth_para_head == (st_CallBack_LoadBoundMeth *)MP_STATE_PORT(loadmeth_para)) - { - MP_STATE_PORT(loadmeth_para) = loadmeth_para_head->next; - qpy_callbackdeal_trace("loadmeth_para:0x%x", MP_STATE_PORT(loadmeth_para)); - } - else - { - loadmeth_para_tmp->next = loadmeth_para_head->next; - } - break; - } - loadmeth_para_tmp = loadmeth_para_head; - } -#if defined(PLAT_ASR) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_ASR_1602) - Helios_Critical_Exit(rc); -#endif - -} - -void qpy_callback_para_link_mark_in_used(void) -{ - -#if defined(PLAT_ASR) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_ASR_1602) - int rc = Helios_Critical_Enter(); -#endif - st_CallBack_LoadBoundMeth *loadmeth_para_head = (st_CallBack_LoadBoundMeth *)MP_STATE_PORT(loadmeth_para); - for(;loadmeth_para_head != NULL; loadmeth_para_head = loadmeth_para_head->next) - { - if(NULL != loadmeth_para_head->arg) - { - gc_collect_root((void **)&loadmeth_para_head->arg, 1); - } - } -#if defined(PLAT_ASR) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_ASR_1602) - Helios_Critical_Exit(rc); -#endif - -} - - -void qpy_callback_para_link_free_all(void) -{ -#if defined(PLAT_ASR) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_ASR_1602) - int rc = Helios_Critical_Enter(); -#endif - st_CallBack_LoadBoundMeth *loadmeth_para_head = (st_CallBack_LoadBoundMeth *)MP_STATE_PORT(loadmeth_para); - st_CallBack_LoadBoundMeth *loadmeth_para_tmp = NULL; - while(loadmeth_para_head != NULL) - { - loadmeth_para_tmp = loadmeth_para_head; - loadmeth_para_head = loadmeth_para_head->next; - free(loadmeth_para_tmp); - } - MP_STATE_PORT(loadmeth_para) = NULL; -#if defined(PLAT_ASR) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_ASR_1602) - Helios_Critical_Exit(rc); -#endif - -} - - -bool mp_sched_empty(void); -/* - * Resolve the crash issue when non-Python threads apply for GC memory and throw exceptions when memory application fails - */ -void qpy_callback_deal_thread(void * args_in) -{ -#if !defined(PLAT_RDA) - qpy_callback_deal_queue = Helios_MsgQ_Create(QPY_CALLBACK_DEAL_MSG_MAX_NUM, sizeof(st_CallBack_Deal)); -#endif - callback_deal_thread_entry_args_t *args = (callback_deal_thread_entry_args_t *)args_in; - mp_state_thread_t ts; - mp_thread_set_state(&ts); - st_CallBack_Deal msg = {0}; - - mp_stack_set_top(&ts + 1); // need to include ts in root-pointer scan -#if defined(PLAT_ECR6600) || defined (PLAT_aic8800m40) - mp_stack_set_limit(QPY_CALLBACK_DEAL_THREAD_STACK_SIZE * sizeof(uint32_t) - 1024); -#else - mp_stack_set_limit(QPY_CALLBACK_DEAL_THREAD_STACK_SIZE - 1024); -#endif - - #if MICROPY_ENABLE_PYSTACK - // TODO threading and pystack is not fully supported, for now just make a small stack - mp_obj_t mini_pystack[128]; - mp_pystack_init(mini_pystack, &mini_pystack[128]); - #endif - - // set locals and globals from the calling context - mp_locals_set(args->dict_locals); - mp_globals_set(args->dict_globals); - m_del_obj(callback_deal_thread_entry_args_t, args); - - MP_THREAD_GIL_ENTER(); - - //mp_thread_start must placed after GIL_ENTER - // signal that we are set up and running - mp_thread_start(); - - while(1) - { - mp_obj_t arg = NULL; - MP_THREAD_GIL_EXIT(); - qpy_callbackdeal_trace("wait msg"); - int ret = Helios_MsgQ_Get(qpy_callback_deal_queue, (void*)&msg, sizeof(msg), HELIOS_WAIT_FOREVER); - qpy_callbackdeal_trace("get msg"); - MP_THREAD_GIL_ENTER(); - if (ret == 0) - { - //Each is processed according to the callback ID - qpy_callbackdeal_trace("callback_type_id:%d", msg.callback_type_id); - switch(msg.callback_type_id) - { - case CALLBACK_TYPE_ID_EXTINT: - { - st_CallBack_Extint *cb_msg = (st_CallBack_Extint *)msg.msg; - mp_obj_tuple_t *pair = MP_OBJ_TO_PTR(cb_msg->callback.arg); - pair->items[0] = mp_obj_new_int(cb_msg->pin_no); - pair->items[1] = mp_obj_new_int(cb_msg->edge); - // mp_obj_t extint_list[2] = { - // mp_obj_new_int(cb_msg->pin_no), - // mp_obj_new_int(cb_msg->edge), - // }; - // arg = mp_obj_new_list(2, extint_list); - mp_sched_schedule_ex(&cb_msg->callback, cb_msg->callback.arg); - } - break; - case CALLBACK_TYPE_ID_AUDIO_RECORD: - { - st_CallBack_AudioRecord *cb_msg = (st_CallBack_AudioRecord *)msg.msg; - mp_obj_t audio_cb[3] = { - mp_obj_new_str(cb_msg->p_data,strlen(cb_msg->p_data)), - mp_obj_new_int(cb_msg->len), - mp_obj_new_int(cb_msg->res), - }; - if(RECORE_TYPE_FILE == cb_msg->record_type && NULL != cb_msg->p_data) { - free(cb_msg->p_data); - } - arg = mp_obj_new_list(3, audio_cb); - mp_sched_schedule_ex(&cb_msg->callback, arg); - #if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_Unisoc_8910_R06) - if (RECORE_TYPE_STREAM == cb_msg->record_type) - { - MP_THREAD_GIL_EXIT(); - Helios_msleep(10); - MP_THREAD_GIL_ENTER(); - } - #endif - } - break; - case CALLBACK_TYPE_ID_VOICECALL_RECORD: - { - st_CallBack_AudioRecord *cb_msg = (st_CallBack_AudioRecord *)msg.msg; - mp_obj_t audio_cb[3] = { - mp_obj_new_str(cb_msg->p_data,strlen(cb_msg->p_data)), - mp_obj_new_int(cb_msg->len), - mp_obj_new_int(cb_msg->res), - }; - - arg = mp_obj_new_list(3, audio_cb); - mp_sched_schedule_ex(&cb_msg->callback, arg); - } - break; - #if MICROPY_QPY_MODULE_QUECIOT - case CALLBACK_TYPE_ID_QUETCH_CALLCB: - { - st_CallBack_Queth cb_msg; - memcpy(&cb_msg,msg.msg,sizeof(st_CallBack_Queth)); - mp_obj_t tuple[] = - { - mp_obj_new_int_from_uint(cb_msg.event), - mp_obj_new_int_from_uint(cb_msg.errcode), - mp_obj_new_bytes(cb_msg.valueT, cb_msg.valLen) - }; - if ( cb_msg.valueT != NULL ) - free(cb_msg.valueT); - free(msg.msg); - mp_sched_schedule_ex(&(cb_msg.call_cb),mp_obj_new_tuple(3, tuple)); - } - break; - #endif //end MICROPY_QPY_MODULE_QUECIOT - #if MICROPY_QPY_MODULE_POC - case CALLBACK_TYPE_ID_POC: - { - qpy_poc_msg_proc(msg.msg); - } - break; - #endif //end MICROPY_QPY_MODULE_POC - #if MICROPY_QPY_MACHINE_KEYPAD - case CALLBACK_TYPE_ID_KEYPAD: - { - st_CallBack_Keypad *cb_msg = (st_CallBack_Keypad *)msg.msg; - mp_obj_t keypad_list[3] = - { - mp_obj_new_int(cb_msg->event_id), - mp_obj_new_int(cb_msg->row), - mp_obj_new_int(cb_msg->col), - }; - arg = mp_obj_new_list(3, keypad_list); - mp_sched_schedule_ex(&cb_msg->callback, arg); - - } - break; - #endif - #if MICROPY_QPY_SENSOR_ICC_KEY - case CALLBACK_TYPE_ID_ICCKEY: - { - st_CallBack_IccKey *cb_msg = (st_CallBack_IccKey *)msg.msg; - mp_sched_schedule_ex(&cb_msg->callback, mp_obj_new_int(cb_msg->key_event)); - } - break; - #endif - - #if MICROPY_QPY_MACHINE_KEY - case CALLBACK_TYPE_ID_KEY: - { - st_CallBack_Key *cb_msg = (st_CallBack_Key *)msg.msg; - mp_obj_t key_list[2] = { - mp_obj_new_int(cb_msg->gpio_number), - mp_obj_new_int(cb_msg->key_event), - }; - arg = mp_obj_new_list(2, key_list); - mp_sched_schedule_ex(&cb_msg->callback, arg); - } - break; - #endif - #if MICROPY_QPY_SENSOR_HANDMIC_KEY - case CALLBACK_TYPE_ID_HANDMIC_KEY: - { - st_CallBack_Handmic *cb_msg = (st_CallBack_Handmic *)msg.msg; - mp_obj_t key_list[2] = { - mp_obj_new_int(cb_msg->key_state), - mp_obj_new_int(cb_msg->key_value), - }; - arg = mp_obj_new_list(2, key_list); - mp_sched_schedule_ex(&cb_msg->callback, arg); - } - break; - #endif - #if MICROPY_QPY_MODULE_EXTUART_WK2114 - case CALLBACK_TYPE_ID_WK2114: - { - st_CallBack_Wk2114 *cb_msg = (st_CallBack_Wk2114 *)msg.msg; - mp_obj_t key_list[3] = { - mp_obj_new_int(cb_msg->int_type), - mp_obj_new_int(cb_msg->port), - mp_obj_new_int(cb_msg->read_lenth), - }; - arg = mp_obj_new_list(3, key_list); - mp_sched_schedule_ex(&cb_msg->callback, arg); - } - break; - #endif - #if MICROPY_QPY_MODULE_JRTC - case CALLBACK_TYPE_ID_JRTC: - { - st_CallBack_jrtc *cb_msg = (st_CallBack_jrtc *)msg.msg; - arg = mp_obj_new_int(cb_msg->result); - mp_sched_schedule_ex(&cb_msg->callback, arg); - - } - break; - #endif - #if MICROPY_QPY_MODULE_GPIO_ENCODER - case CALLBACK_TYPE_ID_ENCODER: - { - st_CallBack_Encoder *cb_msg = (st_CallBack_Encoder *)msg.msg; - arg = mp_obj_new_int(cb_msg->spin_direct); - mp_sched_schedule_ex(&cb_msg->callback, arg); - } - break; - #endif - #if MICROPY_QPY_MODULE_EXTGPIO_AW9523 - case CALLBACK_TYPE_ID_AW9523: - { - st_CallBack_AW9523 *cb_msg = (st_CallBack_AW9523 *)msg.msg; - mp_obj_t aw9523_list[2] = { - mp_obj_new_int(cb_msg->pin_no), - mp_obj_new_int(cb_msg->pin_level), - }; - arg = mp_obj_new_list(2, aw9523_list); - mp_sched_schedule_ex(&cb_msg->callback, arg); - } - break; - #endif - case CALLBACK_TYPE_ID_TP: - { - st_CallBack_TP *cb_msg = (st_CallBack_TP *)msg.msg; - mp_sched_schedule_ex(&cb_msg->callback, mp_obj_new_int(cb_msg->state)); - } - break; - #if MICROPY_QPY_MODULE_BT - case CALLBACK_TYPE_ID_BT: - { - qpy_bt_msg_proc(msg.msg); - break; - } - #endif - #if MICROPY_QPY_MODULE_BLE - case CALLBACK_TYPE_ID_BLE: - { - qpy_ble_msg_proc(msg.msg); - break; - } - #endif - case CALLBACK_TYPE_ID_LOAD_BOUNDMETH: - { - st_CallBack_LoadBoundMeth *cb_msg = (st_CallBack_LoadBoundMeth *)msg.msg; - qpy_callbackdeal_trace("cb_msg:0x%x", cb_msg); - qpy_callback_para_node_delete(cb_msg); - - mp_obj_t cb = mp_load_attr(cb_msg->callback->method_self, cb_msg->callback->method_name); - qpy_callbackdeal_trace("cb:0x%x", cb); - mp_call_function_1_protected(cb, cb_msg->arg); - break; - } - #if MICROPY_QPY_MODULE_ALIPAY - case CALLBACK_TYPE_ID_ALIPAY: - { - st_CallBack_ALIPAY *alipay_msg = (st_CallBack_ALIPAY *)msg.msg; - mp_obj_t alipay_cb[5] = - { - mp_obj_new_int(alipay_msg->cmd), - mp_obj_new_int(alipay_msg->rsp_code), - mp_obj_new_str((char *)(alipay_msg->result), (char *)(strlen(alipay_msg->result))), - mp_obj_new_int(alipay_msg->result_len), - mp_obj_new_str((char *)(alipay_msg->userdata), (char *)(strlen(alipay_msg->userdata))), - }; - mp_sched_schedule_ex(&alipay_msg->callback, mp_obj_new_tuple(5, alipay_cb)); - break; - } - #endif - #if MICROPY_QPY_LPM_WAKEUP - case CALLBACK_TYPE_ID_WAKEUP: - { - st_CallBack_Wakeup *cb_msg = (st_CallBack_Wakeup *)msg.msg; - mp_sched_schedule_ex(&cb_msg->callback, mp_obj_new_int(cb_msg->level)); - break; - } - #endif - #if MICROPY_QPY_MACHINE_UART - case CALLBACK_TYPE_ID_UART: - { - st_CallBack_Uart *uart_msg = (st_CallBack_Uart *)msg.msg; - // mp_obj_t uart_cb[3] = - // { - // mp_obj_new_int(uart_msg->ind_type), - // mp_obj_new_int(uart_msg->port), - // mp_obj_new_int(uart_msg->size), - // }; - // arg = mp_obj_new_list(3,uart_cb); - mp_obj_tuple_t *pair = MP_OBJ_TO_PTR(uart_msg->callback.arg); - pair->items[0] = mp_obj_new_int(uart_msg->ind_type); - pair->items[1] = mp_obj_new_int(uart_msg->port); - pair->items[2] = mp_obj_new_int(uart_msg->size); - mp_sched_schedule_ex(&uart_msg->callback, uart_msg->callback.arg); - break; - } - #endif - #if MICROPY_QPY_MODULE_NET - case CALLBACK_TYPE_ID_NET: - { - qpy_callbackdeal_trace("callback_type_id:CALLBACK_TYPE_ID_NET = %d", msg.callback_type_id); - st_CallBack_Net *net_msg = (st_CallBack_Net *)msg.msg; - mp_obj_tuple_t *pair = MP_OBJ_TO_PTR(net_msg->callback.arg); - pair->items[0] = mp_obj_new_int(net_msg->event_id); - pair->items[1] = mp_obj_new_int(net_msg->status); - pair->items[2] = mp_obj_new_int(net_msg->lac); - pair->items[3] = mp_obj_new_int(net_msg->cid); - pair->items[4] = mp_obj_new_int(net_msg->act); - - mp_sched_schedule_ex(&net_msg->callback, net_msg->callback.arg); - break; - } - #endif - #if MICROPY_QPY_MODULE_DATACALL - case CALLBACK_TYPE_ID_DATACALL: - { - st_CallBack_Datacall *datacall_msg = (st_CallBack_Datacall *)msg.msg; - mp_obj_tuple_t *pair = MP_OBJ_TO_PTR(datacall_msg->callback.arg); - pair->items[0] = mp_obj_new_int(datacall_msg->profile_idx); - pair->items[1] = mp_obj_new_int(datacall_msg->nw_status); - pair->items[2] = mp_obj_new_int(datacall_msg->sim_id); - - mp_sched_schedule_ex(&datacall_msg->callback, datacall_msg->callback.arg); - break; - } - #endif - #if MICROPY_QPY_MODULE_ALIPAY_COLLECTION - case CALLBACK_TYPE_ID_ALIPAY_COLLECTION: - { - st_CallBack_ALIPAY_COLLECTION *alipay_collection_msg = (st_CallBack_ALIPAY_COLLECTION *)msg.msg; - mp_obj_t alipay_collection_cb[2] = - { - mp_obj_new_int(alipay_collection_msg->msgID), - mp_obj_new_int(alipay_collection_msg->data), - }; - mp_sched_schedule_ex(&alipay_collection_msg->callback, mp_obj_new_tuple(2, alipay_collection_cb)); - break; - } - #endif - #if MICROPY_QPY_MODULE_SMS - case CALLBACK_TYPE_ID_SMS: - { - st_CallBack_SMS *sms_msg = (st_CallBack_SMS *)msg.msg; - mp_obj_t sms_cb[3] = - { - mp_obj_new_int(sms_msg->sim_id), - mp_obj_new_int(sms_msg->index), - mp_obj_new_str(sms_msg->storage, strlen(sms_msg->storage)) - }; - mp_sched_schedule_ex(&sms_msg->callback, mp_obj_new_tuple(3, sms_cb)); - break; - } - #endif - #if MICROPY_QPY_MODULE_SIF - case CALLBACK_TYPE_ID_SIF: - { - st_CallBack_SIF *sif_msg = (st_CallBack_SIF *)msg.msg; - mp_sched_schedule_ex(&sif_msg->callback, mp_obj_new_bytes(sif_msg->data, sif_msg->data_len)); - break; - } - #endif - #if defined(BOARD_BC32RA) || defined(BOARD_BC92RB) || defined(PLAT_SONY_ALT1350)//forrest.liu@20231228 add for FAE-102027 dump issue - #if MICROPY_QPY_MACHINE_TIMER - case CALLBACK_TYPE_ID_TIMER: - { - st_CallBack_Timer *timer_msg = (st_CallBack_Timer *)msg.msg; - - mp_sched_schedule_ex(&timer_msg->callback, mp_const_none); - break; - } - #endif - #endif - #if defined(BOARD_EC600MCN_LA_POC_XBND) || defined(BOARD_EC600MCN_LE_POC_XBND) || defined(BOARD_EC600MEU_LA_POC_XBND) \ - || defined(BOARD_EC600MLA_LA_POC_XBND) - case CALLBACK_TYPE_ID_POCSPEAK: - { - st_CallBack_PocSpeak *pocspeak_msg = (st_CallBack_PocSpeak *)msg.msg; - mp_obj_t pocspeak_list[2] = - { - mp_obj_new_int(pocspeak_msg->speak_op), - mp_obj_new_int(pocspeak_msg->speak_result), - }; - arg = mp_obj_new_list(2, pocspeak_list); - mp_sched_schedule_ex(&pocspeak_msg->callback, arg); - break; - } - #endif -#if MICROPY_QPY_MODULE_NFC - case CALLBACK_TYPE_ID_NFC: - { - st_CallBack_nfc *nfc_msg = (st_CallBack_nfc *)msg.msg; - - mp_obj_t nfc_list[2] = {0}; - nfc_list[0] = mp_obj_new_int(nfc_msg->oid); - - if(nfc_msg->data && nfc_msg->data_len != 0) - { - nfc_list[1] = mp_obj_new_bytes(nfc_msg->data, nfc_msg->data_len); - arg = mp_obj_new_list(2, nfc_list); - } else { - arg = mp_obj_new_list(1, nfc_list); - } - mp_sched_schedule_ex(&nfc_msg->callback, arg); - - if(nfc_msg->data) { - free(nfc_msg->data); - nfc_msg->data = NULL; - } - - break; - } -#endif -#if MICROPY_QPY_SENSOR_VC9202 - - case CALLBACK_TYPE_ID_VC9202: - { - st_CallBack_Sensor_VC9202 *cb_msg = (st_CallBack_Sensor_VC9202 *)msg.msg; - mp_obj_t vc9202_list[3] = { - mp_obj_new_int(cb_msg->work_mode), - mp_obj_new_int(cb_msg->value), - mp_obj_new_int(cb_msg->measure_mode), - }; - arg = mp_obj_new_list(3, vc9202_list); - mp_sched_schedule_ex(&cb_msg->callback, arg); - } - break; -#endif -#if MICROPY_QPY_MODULE_LWM2M - case CALLBACK_TYPE_ID_LWM2M:{ - qpy_lwm2m_msg_proc(msg.msg); - break; - } -#endif -#if MICROPY_QPY_MODULE_ESIM && MICROPY_QPY_MODULE_ESIM_IPA - case CALLBACK_TYPE_ID_ESIM_IPA:{ - qpy_esim_msg_proc(msg.msg); - break; - } -#endif - case CALLBACK_TYPE_ID_NONE: - default: - break; - } - - #if defined(BOARD_BC32RA) || defined(BOARD_BC92RB) || defined(PLAT_SONY_ALT1350)//forrest.liu@20231228 modify for FAE-102027 dump issue - if(msg.callback_type_id != CALLBACK_TYPE_ID_TIMER) - { - if(msg.msg) { - free(msg.msg); - } - } - memset(&msg, 0, sizeof(st_CallBack_Deal)); - #else - if(msg.msg) { - free(msg.msg); - msg.msg = NULL; - } - memset(&msg, 0, sizeof(st_CallBack_Deal)); - #endif - - } - else - { -#if defined(BOARD_BC32RA) || defined(BOARD_BC92RB) || defined(PLAT_SONY_ALT1350)//forrest.liu@20231228 modify for FAE-102027 dump issue - if(msg.callback_type_id != CALLBACK_TYPE_ID_TIMER) - { - if(msg.msg) { - free(msg.msg); - } - } - memset(&msg, 0, sizeof(st_CallBack_Deal)); -#else - if(msg.msg) { - free(msg.msg); - } - memset(&msg, 0, sizeof(st_CallBack_Deal)); -#endif - } - } -} - -#endif - -MP_REGISTER_ROOT_POINTER(void * loadmeth_para); diff --git a/ports/quectel/callbackdeal.h b/ports/quectel/callbackdeal.h deleted file mode 100644 index 465ca378053c2..0000000000000 --- a/ports/quectel/callbackdeal.h +++ /dev/null @@ -1,389 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020-2021 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. - */ - -// empty file -#ifndef __CALLBACKDEAL_H__ -#define __CALLBACKDEAL_H__ - -#include "py/runtime.h" - -#if MICROPY_QPY_MODULE_BT || MICROPY_QPY_MODULE_BLE -#include "helios_btble.h" -#endif - -#if MICROPY_QPY_MODULE_ALIPAY -#include "helios_aliiot.h" -#endif - -#if MICROPY_QPY_MACHINE_UART -#include "helios_uart.h" -#endif - -#if MICROPY_ENABLE_CALLBACK_DEAL - -typedef struct _c_callback_t { - bool is_method; - mp_obj_t method_self; - qstr method_name; - mp_obj_t cb; - mp_obj_t arg; -}c_callback_t; - -typedef struct{ - uint8_t callback_type_id; - void *msg; -}st_CallBack_Deal; - -enum { - CALLBACK_TYPE_ID_NONE, - CALLBACK_TYPE_ID_LOAD_BOUNDMETH, - CALLBACK_TYPE_ID_EXTINT, - CALLBACK_TYPE_ID_OSTIMER, - CALLBACK_TYPE_ID_HWTIMER, - CALLBACK_TYPE_ID_AUDIO_AUDIO, - CALLBACK_TYPE_ID_AUDIO_RECORD, - CALLBACK_TYPE_ID_AUDIO_TTS, - CALLBACK_TYPE_ID_CAM_CAP, - CALLBACK_TYPE_ID_VOICECALL_RECORD, -#if MICROPY_QPY_MODULE_QUECIOT - CALLBACK_TYPE_ID_QUETCH_CALLCB, -#endif -#if MICROPY_QPY_MODULE_POC - CALLBACK_TYPE_ID_POC, -#endif -#if MICROPY_QPY_MACHINE_KEYPAD - CALLBACK_TYPE_ID_KEYPAD, -#endif -#if MICROPY_QPY_MACHINE_KEY - CALLBACK_TYPE_ID_KEY, -#endif -#if MICROPY_QPY_SENSOR_ICC_KEY - CALLBACK_TYPE_ID_ICCKEY, -#endif -#if MICROPY_QPY_SENSOR_HANDMIC_KEY - CALLBACK_TYPE_ID_HANDMIC_KEY, -#endif -#if MICROPY_QPY_MODULE_EXTUART_WK2114 - CALLBACK_TYPE_ID_WK2114, -#endif -#if MICROPY_QPY_MODULE_GPIO_ENCODER - CALLBACK_TYPE_ID_ENCODER, -#endif -#if MICROPY_QPY_MODULE_EXTGPIO_AW9523 - CALLBACK_TYPE_ID_AW9523, -#endif - CALLBACK_TYPE_ID_TP, -#if MICROPY_QPY_MODULE_BT - CALLBACK_TYPE_ID_BT, -#endif -#if MICROPY_QPY_MODULE_BLE - CALLBACK_TYPE_ID_BLE, -#endif -#if MICROPY_QPY_MODULE_ALIPAY - CALLBACK_TYPE_ID_ALIPAY, -#endif -#if MICROPY_QPY_LPM_WAKEUP - CALLBACK_TYPE_ID_WAKEUP, -#endif -#if MICROPY_QPY_MACHINE_UART - CALLBACK_TYPE_ID_UART, -#endif -#if MICROPY_QPY_MODULE_NET - CALLBACK_TYPE_ID_NET, -#endif -#if MICROPY_QPY_MODULE_DATACALL - CALLBACK_TYPE_ID_DATACALL, -#endif -#if MICROPY_QPY_MODULE_ALIPAY_COLLECTION - CALLBACK_TYPE_ID_ALIPAY_COLLECTION, -#endif -#if MICROPY_QPY_MODULE_SMS - CALLBACK_TYPE_ID_SMS, -#endif -#if MICROPY_QPY_MODULE_JRTC - CALLBACK_TYPE_ID_JRTC, -#endif -#if MICROPY_QPY_MODULE_SIF - CALLBACK_TYPE_ID_SIF, -#endif -#if defined(BOARD_BC32RA) || defined(BOARD_BC92RB) || defined(PLAT_SONY_ALT1350) -#if MICROPY_QPY_MACHINE_TIMER - CALLBACK_TYPE_ID_TIMER, -#endif -#endif -#if defined(BOARD_EC600MCN_LA_POC_XBND) || defined(BOARD_EC600MCN_LE_POC_XBND) || defined(BOARD_EC600MEU_LA_POC_XBND)\ - || defined(BOARD_EC600MLA_LA_POC_XBND) - CALLBACK_TYPE_ID_POCSPEAK, -#endif -#if MICROPY_QPY_MODULE_NFC - CALLBACK_TYPE_ID_NFC, -#endif -#if MICROPY_QPY_SENSOR_VC9202 - CALLBACK_TYPE_ID_VC9202, -#endif -#if MICROPY_QPY_MODULE_LWM2M - CALLBACK_TYPE_ID_LWM2M, -#endif -#if MICROPY_QPY_MODULE_ESIM && MICROPY_QPY_MODULE_ESIM_IPA - CALLBACK_TYPE_ID_ESIM_IPA, -#endif -}; - -typedef struct CallBack_LoadBoundMeth{ - c_callback_t *callback; - void *arg; - struct CallBack_LoadBoundMeth *next; -}st_CallBack_LoadBoundMeth; - -typedef struct{ - uint8_t key_event; - c_callback_t callback; -}st_CallBack_IccKey; - -typedef struct{ - uint8_t gpio_number; - uint8_t key_event; - c_callback_t callback; -}st_CallBack_Key; - -typedef struct{ - uint8_t state; - c_callback_t callback; -}st_CallBack_TP; - -typedef struct{ - uint8_t pin_no; - uint8_t edge; - c_callback_t callback; -}st_CallBack_Extint; - -typedef struct{ - uint8_t key_value; - uint8_t key_state; - c_callback_t callback; -}st_CallBack_Handmic; - -typedef struct{ - uint32_t int_type; - uint32_t port; - uint32_t read_lenth; - c_callback_t callback; -}st_CallBack_Wk2114; - -typedef struct{ - uint8_t pin_no; - uint8_t pin_level; - c_callback_t callback; -}st_CallBack_AW9523; - -typedef struct{ - uint32_t spin_direct; - c_callback_t callback; -}st_CallBack_Encoder; - -enum { - POC_CAL_ELEM_INT, - POC_CAL_ELEM_STR, - POC_CAL_ELEM_UINT64, - POC_CAL_ELEM_ARRAY_INT, - POC_CAL_ELEM_FLOAT, -}; - -typedef struct -{ - int type; - void* data; -}st_CallBack_POC_ELEM; - -typedef struct -{ - st_CallBack_POC_ELEM *para; - int len; - c_callback_t callback; -}st_CallBack_POC; - - -enum {RECORE_TYPE_FILE,RECORE_TYPE_STREAM}; -typedef struct{ - int record_type; - char * p_data; - int len; - int res; - c_callback_t callback; -}st_CallBack_AudioRecord; -typedef struct{ - uint32_t event; - uint32_t errcode; - void *valueT; - uint32_t valLen; - c_callback_t call_cb; -}st_CallBack_Queth; - -typedef struct{ - mp_obj_t fun_in; - size_t n_args; - size_t n_kw; - mp_obj_t *args; -}st_CallBack_lvgl; - -typedef struct{ - uint32_t result; - c_callback_t callback; -}st_CallBack_jrtc; - -typedef struct{ - uint8_t event_id; - uint8_t row; - uint8_t col; - c_callback_t callback; -}st_CallBack_Keypad; - -#if MICROPY_QPY_SENSOR_VC9202 -typedef struct{ - uint32_t work_mode; - uint16_t value; - uint32_t measure_mode; - c_callback_t callback; -}st_CallBack_Sensor_VC9202; -#endif -#if defined(BOARD_BC32RA) || defined(BOARD_BC92RB) || defined(PLAT_SONY_ALT1350) -#if MICROPY_QPY_MACHINE_TIMER -typedef struct{ - c_callback_t callback; -}st_CallBack_Timer; -#endif -#endif - -#if defined(BOARD_EC600MCN_LA_POC_XBND) || defined(BOARD_EC600MCN_LE_POC_XBND) || defined(BOARD_EC600MEU_LA_POC_XBND)\ - || defined(BOARD_EC600MLA_LA_POC_XBND) -typedef struct{ - uint8_t speak_op; - int speak_result; - c_callback_t callback; -}st_CallBack_PocSpeak; -#endif -#if MICROPY_QPY_MACHINE_UART -typedef struct{ - uint64_t ind_type; - Helios_UARTNum port; - uint64_t size; - c_callback_t callback; -}st_CallBack_Uart; -#endif - -#if MICROPY_QPY_MODULE_NFC -typedef struct{ - uint16_t oid; - void* data; - uint8_t data_len; - c_callback_t callback; -}st_CallBack_nfc; -#endif - -#if MICROPY_QPY_MODULE_NET -typedef struct{ - int32_t event_id; - int32_t status; - int32_t act; - int32_t lac; - int32_t cid; - c_callback_t callback; -}st_CallBack_Net; -#endif - -#if MICROPY_QPY_MODULE_DATACALL -typedef struct{ - int32_t profile_idx; - uint8_t sim_id; - int32_t nw_status; - c_callback_t callback; -}st_CallBack_Datacall; -#endif - -#if MICROPY_QPY_MODULE_SMS -typedef struct{ - uint8_t sim_id; - uint8_t index; - char storage[5]; - c_callback_t callback; -}st_CallBack_SMS; -#endif - -#if MICROPY_QPY_MODULE_BT || MICROPY_QPY_MODULE_BLE -typedef struct{ - //void *msg; - Helios_Event event; - c_callback_t callback; -}st_CallBack_BT; -#endif - -#if MICROPY_QPY_MODULE_ALIPAY -typedef struct{ - helios_pay_msg_cmd_t cmd; - helios_pay_rsp_code_t rsp_code; - char *result; - int result_len; - void *userdata; - c_callback_t callback; -}st_CallBack_ALIPAY; -#endif - -#if MICROPY_QPY_MODULE_ALIPAY_COLLECTION -typedef struct{ - int msgID; - int data; - c_callback_t callback; -}st_CallBack_ALIPAY_COLLECTION; -#endif - -#if MICROPY_QPY_LPM_WAKEUP -typedef struct{ - uint8_t level; - c_callback_t callback; -} st_CallBack_Wakeup; -#endif - -#if MICROPY_QPY_MODULE_SIF -typedef struct{ - int data_len; - uint8_t *data; - c_callback_t callback; -} st_CallBack_SIF; -#endif - -bool mp_sched_schedule_callback_register(c_callback_t *callback, mp_obj_t func_obj); -bool mp_sched_schedule_ex(c_callback_t *callback, mp_obj_t arg); - -void qpy_callback_deal_init(void); -void qpy_callback_deal_deinit(void); -int qpy_send_msg_to_callback_deal_thread(uint8_t id, void *msg); -bool qpy_is_callback_deal_thread(void); -st_CallBack_LoadBoundMeth * qpy_callback_para_node_add(c_callback_t *callback, mp_obj_t arg); -void qpy_callback_para_node_delete(st_CallBack_LoadBoundMeth *cb_msg); -void qpy_callback_para_link_free_all(void); -void qpy_callback_para_link_mark_in_used(void); -#endif -#endif //__CALLBACKDEAL_H__ \ No newline at end of file diff --git a/ports/quectel/machine_extint.c b/ports/quectel/machine_extint.c deleted file mode 100644 index 6eabf508f6889..0000000000000 --- a/ports/quectel/machine_extint.c +++ /dev/null @@ -1,734 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020-2021 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 - -#include "runtime.h" -#include "gc.h" -#include "mphal.h" -#include "gccollect.h" - -#if MICROPY_QPY_MACHINE_EXTINT -#include "helios_pin.h" -#include "helios_extint.h" -#include "helios_debug.h" -#include "callbackdeal.h" -#include "helios_os.h" - -//#if defined(PLAT_EIGEN) -static Helios_Thread_t thread_id = 0; -static Helios_MsgQ_t extint_queue = 0; -typedef struct -{ - uint8_t msg_type; - uint8_t pin; - uint8_t edge; - void* cb; -}extint_Msg; - -//#endif -#if 1 -#define EXTINT_LOG(msg, ...) custom_log("extint", msg, ##__VA_ARGS__) -#else -#define EXTINT_LOG(msg, ...) -#endif -/* sample time (ms) */ -#define EXTINT_SAMPLE_TIME (10) - -extern int Helios_GPIO_GetLevel(Helios_GPIONum gpio_num); -const mp_obj_type_t machine_extint_type; - -#if defined(BOARD_EG810MCN_GA_ALIPAY) || defined(BOARD_EG810MCN_GA_VOLTE) -static int __fastIntGpio = 0xffff; -#endif - -typedef struct { - mp_obj_base_t base; - mp_int_t line; - mp_int_t mode; - mp_int_t pull; - mp_int_t fliter_time; - c_callback_t callback; -} extint_obj_t; - - -typedef struct { - mp_int_t rising_count; - mp_int_t falling_count; -} extint_count_t; - -#if defined(PLAT_aic8800m40) -typedef void(*eint_handler_t)(int EDGE); -#else -typedef void(*eint_handler_t)(void); - -#endif - -static extint_obj_t *extint_obj[HELIOS_GPIOMAX]; -static extint_count_t extint_count[HELIOS_GPIOMAX] = {0}; -static Helios_OSTimer_t extint_fliter_timer[HELIOS_GPIOMAX] = {0}; -static uint8_t extint_fliter_timer_is_start[HELIOS_GPIOMAX] = {0}; - -enum { - HELIOS_EXTINT_RISING, - HELIOS_EXTINT_FALLING, -}; - -#define EINT_HANDLER_DEF(n) handler##n -#define PLAT_EINT_HANDLER_DEF(n) BOOST_PP_REPEAT_1(n,EINT_HANDLER_DEF) - -/* -** Jayceon-20200908: -** Replace function mp_call_function_1_protected() with mp_sched_schedule_ex to slove the dump problem. -*/ -#if MICROPY_ENABLE_CALLBACK_DEAL -#define EXTINT_CALLBACK_OP(X, edge) do{ \ - st_CallBack_Extint *extint = malloc(sizeof(st_CallBack_Extint)); \ - if(NULL != extint) { \ - extint->pin_no = X; \ - extint->edge = edge; \ - extint->callback = extint_obj[X]->callback; \ - if(qpy_send_msg_to_callback_deal_thread(CALLBACK_TYPE_ID_EXTINT, extint)) \ - { \ - free(extint); \ - } \ - } \ - }while(0) -#else -#define EXTINT_CALLBACK_OP(X, edge) do{ \ - GC_STACKTOP_SET(); \ - mp_obj_t extint_list[2] = { \ - mp_obj_new_int(X), \ - mp_obj_new_int(edge), \ - }; \ - mp_sched_schedule(&extint_obj[X]->callback, mp_obj_new_list(2, extint_list)); \ - GC_STACKTOP_CLEAR(); \ - }while(0) - -#endif - - -#if defined(PLAT_aic8800m40) -#define HANDLER_FUN(X) \ -static void fliter_timer_handler##X(void *args) { \ - int edge = (int)args; \ - static uint32_t extint_fliter_count = 0; \ - uint32_t extint_fliter_count_max = extint_obj[X]->fliter_time / EXTINT_SAMPLE_TIME; \ - int level = Helios_GPIO_GetLevel(X); \ - switch (edge) { \ - case HELIOS_EXTINT_RISING: \ - if (level != 1) { \ - extint_fliter_count = 0; \ - } \ - break; \ - case HELIOS_EXTINT_FALLING: \ - if (level != 0) { \ - extint_fliter_count = 0; \ - } \ - break; \ - } \ - if (++extint_fliter_count > extint_fliter_count_max) { \ - Helios_OSTimer_Stop(extint_fliter_timer[X]); \ - extint_fliter_count = 0; \ - extint_fliter_timer_is_start[X] = false; \ - EXTINT_CALLBACK_OP(X, edge); \ - } \ -} \ -static void handler##X(int EDGE) \ -{ \ - int edge = EDGE; \ - if (extint_obj[X]->callback.cb != mp_const_none && \ - ((mp_sched_num_pending() < MICROPY_SCHEDULER_DEPTH))) \ - { \ - if (extint_obj[X]->fliter_time > 0 && !extint_fliter_timer_is_start[X]) { \ - if (!extint_fliter_timer[X]) { \ - extint_fliter_timer[X] = Helios_OSTimer_Create(); \ - if (!extint_fliter_timer[X]) { \ - EXTINT_LOG("error: extint fliter timer create failed!"); \ - EXTINT_CALLBACK_OP(X, edge); \ - } \ - } else { \ - Helios_OSTimerAttr attr = { \ - .ms = EXTINT_SAMPLE_TIME, \ - .cycle_enable = 1, \ - .cb = fliter_timer_handler##X, \ - .argv = (void*)edge \ - }; \ - Helios_OSTimer_Start(extint_fliter_timer[X], &attr); \ - extint_fliter_timer_is_start[X] = true; \ - } \ - } else if(extint_obj[X]->fliter_time == 0){ \ - EXTINT_CALLBACK_OP(X, edge); \ - } \ - } \ - Helios_ExtInt_Enable(extint_obj[X]->line); \ -} -#else -#define HANDLER_FUN(X) \ -static void fliter_timer_handler##X(void *args) { \ - int edge = (int)args; \ - static uint32_t extint_fliter_count = 0; \ - uint32_t extint_fliter_count_max = extint_obj[X]->fliter_time / EXTINT_SAMPLE_TIME; \ - int level = Helios_GPIO_GetLevel(X); \ - switch (edge) { \ - case HELIOS_EXTINT_RISING: \ - if (level != 1) { \ - Helios_OSTimer_Stop(extint_fliter_timer[X]); \ - extint_fliter_count = 0; \ - extint_fliter_timer_is_start[X] = false;\ - } \ - break; \ - case HELIOS_EXTINT_FALLING: \ - if (level != 0) { \ - Helios_OSTimer_Stop(extint_fliter_timer[X]); \ - extint_fliter_count = 0; \ - extint_fliter_timer_is_start[X] = false;\ - } \ - break; \ - } \ - if (++extint_fliter_count > extint_fliter_count_max) { \ - Helios_OSTimer_Stop(extint_fliter_timer[X]); \ - extint_fliter_count = 0; \ - extint_fliter_timer_is_start[X] = false; \ - EXTINT_CALLBACK_OP(X, edge); \ - if(edge == HELIOS_EXTINT_RISING) \ - { \ - extint_count[X].rising_count++; \ - } \ - else \ - { \ - extint_count[X].falling_count++; \ - } \ - } \ - Helios_ExtInt_Enable(extint_obj[X]->line); \ -} \ -static void handler##X(void) \ -{ \ - int edge = HELIOS_EXTINT_RISING;\ - if(extint_obj[X]->mode == HELIOS_EDGE_RISING) \ - { \ - if(extint_obj[X]->fliter_time == 0) \ - { \ - extint_count[X].rising_count++; \ - } \ - } \ - else if(extint_obj[X]->mode == HELIOS_EDGE_FALLING) \ - { \ - edge = HELIOS_EXTINT_FALLING; \ - if(extint_obj[X]->fliter_time == 0) \ - { \ - extint_count[X].falling_count++; \ - } \ - } \ - else \ - { \ - if(Helios_GPIO_GetLevel((Helios_GPIONum)X) == 0) \ - { \ - edge = HELIOS_EXTINT_FALLING; \ - if(extint_obj[X]->fliter_time == 0) \ - { \ - extint_count[X].falling_count++; \ - } \ - } \ - else \ - { \ - if(extint_obj[X]->fliter_time == 0) \ - { \ - extint_count[X].rising_count++; \ - } \ - } \ - } \ - if (extint_obj[X]->callback.cb != mp_const_none && \ - ((mp_sched_num_pending() < MICROPY_SCHEDULER_DEPTH))) \ - { \ - if (extint_obj[X]->fliter_time > 0 && !extint_fliter_timer_is_start[X]) { \ - extint_fliter_timer_is_start[X] = true;\ - if(extint_queue && thread_id) \ - { \ - extint_Msg msg; \ - msg.msg_type = 1;\ - msg.pin = X; \ - msg.edge = edge; \ - msg.cb = fliter_timer_handler##X;\ - Helios_MsgQ_Put(extint_queue, (void *)&msg, sizeof(extint_Msg), HELIOS_NO_WAIT);\ - } \ - else\ - {\ - Helios_OSTimerAttr attr = \ - { \ - .ms = EXTINT_SAMPLE_TIME,\ - .cycle_enable = 1, \ - .cb = fliter_timer_handler##X, \ - .argv = (void*)edge \ - }; \ - if(extint_fliter_timer[X])\ - {\ - Helios_OSTimer_Start(extint_fliter_timer[X], &attr); \ - }\ - }\ - } else if(extint_obj[X]->fliter_time == 0){\ - if(extint_queue && thread_id) \ - { \ - extint_Msg msg; \ - msg.msg_type = 0;\ - msg.pin = X; \ - msg.edge = edge; \ - Helios_MsgQ_Put(extint_queue, (void *)&msg, sizeof(extint_Msg), HELIOS_NO_WAIT);\ - } \ - else \ - { \ - EXTINT_CALLBACK_OP(X, edge); \ - } \ - } \ - } \ - if((extint_obj[X]->fliter_time == 0) && !(extint_queue && thread_id)) \ - { \ - Helios_ExtInt_Enable(extint_obj[X]->line); \ - } \ -} -#endif - - -HANDLER_FUN_0_N(PLAT_GPIO_NUM) - - - - -eint_handler_t eint_handler[HELIOS_GPIOMAX] = { - handler0, PLAT_EINT_HANDLER_DEF(PLAT_GPIO_NUM) -}; - - - -static void extint_count_reset(int offset) { - extint_count[offset].falling_count = 0; - extint_count[offset].rising_count = 0; -} - -/// \method line() -/// Return the line number that the pin is mapped to. -static mp_obj_t extint_obj_line(mp_obj_t self_in) { - extint_obj_t *self = MP_OBJ_TO_PTR(self_in); - return MP_OBJ_NEW_SMALL_INT(self->line); -} -static MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_line_obj, extint_obj_line); - -/// \method enable() -/// Enable a disabled interrupt. -static mp_obj_t extint_obj_enable(mp_obj_t self_in) { - extint_obj_t *self = MP_OBJ_TO_PTR(self_in); - int ret = Helios_ExtInt_Enable((Helios_GPIONum) self->line); - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_enable_obj, extint_obj_enable); - -/// \method disable() -/// Disable the interrupt associated with the ExtInt object. -/// This could be useful for debouncing. -static mp_obj_t extint_obj_disable(mp_obj_t self_in) { - extint_obj_t *self = MP_OBJ_TO_PTR(self_in); - int ret = Helios_ExtInt_Disable((Helios_GPIONum) self->line); - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_disable_obj, extint_obj_disable); - -#if defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) || defined(PLAT_SONY_ALT1350) -static void extint_entry(void * argv) -{ - extint_Msg msg; - int edge; - while(1) - { - Helios_MsgQ_Get(extint_queue, (void *)&msg, sizeof(extint_Msg), HELIOS_WAIT_FOREVER); - edge = msg.edge; - if(msg.msg_type == 1)//start timer - { - if(extint_fliter_timer[msg.pin]) - { - Helios_OSTimerAttr attr = - { - .ms = EXTINT_SAMPLE_TIME, - .cycle_enable = 1, - .cb = (void(*)(void *))msg.cb, - .argv = (void*)edge - }; - if(Helios_OSTimer_Start(extint_fliter_timer[msg.pin], &attr))//eigen 618 plat,we cant call Helios_OSTimer_Start in IRQ - { - } - else - { - } - } - } - else - { - EXTINT_CALLBACK_OP(msg.pin,edge); - Helios_ExtInt_Enable(msg.pin); - } - } -} -#endif -/// \classmethod \constructor(pin, mode, pull, callback) -/// Create an ExtInt object: -/// -/// - `pin` is the pin on which to enable the interrupt (can be a pin object or any valid pin name). -/// - `mode` can be one of: -/// - `ExtInt.IRQ_RISING` - trigger on a rising edge; -/// - `ExtInt.IRQ_FALLING` - trigger on a falling edge; -/// - `ExtInt.IRQ_RISING_FALLING` - trigger on a rising or falling edge. -/// - `pull` can be one of: -/// - `pyb.Pin.PULL_NONE` - no pull up or down resistors; -/// - `pyb.Pin.PULL_UP` - enable the pull-up resistor; -/// - `pyb.Pin.PULL_DOWN` - enable the pull-down resistor. -/// - `callback` is the function to call when the interrupt triggers. The -/// callback function must accept exactly 1 argument, which is the line that -/// triggered the interrupt. -static const mp_arg_t pyb_extint_make_new_args[] = { - { MP_QSTR_pin, MP_ARG_REQUIRED | MP_ARG_INT, {.u_obj = 0} }, - { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_pull, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_callback, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, -#if defined(BOARD_EG810MCN_GA_ALIPAY) || defined(BOARD_EG810MCN_GA_VOLTE) - { MP_QSTR_fast, MP_ARG_INT, {.u_int = 0} }, -#endif - { MP_QSTR_filter_time, MP_ARG_INT, {.u_int = 0} }, -}; -#define PYB_EXTINT_MAKE_NEW_NUM_ARGS MP_ARRAY_SIZE(pyb_extint_make_new_args) - -static mp_obj_t extint_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - // type_in == extint_obj_type - // parse args - mp_arg_val_t vals[PYB_EXTINT_MAKE_NEW_NUM_ARGS]; - mp_arg_parse_all_kw_array(n_args, n_kw, args, PYB_EXTINT_MAKE_NEW_NUM_ARGS, pyb_extint_make_new_args, vals); - -#if !defined(PLAT_ECR6600) - if (vals[0].u_int < HELIOS_GPIO0 || vals[0].u_int > HELIOS_GPIOMAX) { - mp_raise_ValueError(MP_ERROR_TEXT("invalid pin value")); - } -#endif - - if (extint_obj[vals[0].u_int] == NULL) - { - extint_obj[vals[0].u_int] = mp_obj_malloc_with_finaliser(extint_obj_t, &machine_extint_type); - } - extint_obj_t *self = extint_obj[vals[0].u_int]; - self->base.type = type; - self->line = vals[0].u_int; - - self->mode = vals[1].u_int; - if (self->mode < HELIOS_EDGE_RISING || self->mode > HELIOS_EDGE_BOTH) { - mp_raise_ValueError(MP_ERROR_TEXT("invalid mode value")); - } - - self->pull = vals[2].u_int; - if (self->pull < HELIOS_PULL_NONE || self->pull > HELIOS_PULL_DOWN) { - mp_raise_ValueError(MP_ERROR_TEXT("invalid pull value")); - } - - static c_callback_t cb = {0}; - memset(&cb, 0, sizeof(c_callback_t)); - cb.arg = mp_obj_new_tuple(2, NULL); - self->callback = cb; - mp_sched_schedule_callback_register(&self->callback, vals[3].u_obj); - // EXTINT_LOG("ds cb 457!\n"); - - Helios_ExtIntStruct extint_struct = {0}; - extint_struct.gpio_trigger = HELIOS_EDGE_TRIGGER; - extint_struct.gpio_edge = self->mode; - extint_struct.gpio_debounce = HELIOS_DEBOUNCE_EN; - extint_struct.gpio_pull = self->pull; - extint_struct.eint_cb = NULL; - extint_struct.wakeup_eint_cb = eint_handler[self->line]; - - // EXTINT_LOG("%x\n", extint_struct.wakeup_eint_cb); - - Helios_ExtInt_Deinit((Helios_GPIONum) self->line); - - if(0 != Helios_ExtInt_Init((Helios_GPIONum) self->line, &extint_struct)) { - mp_raise_ValueError(MP_ERROR_TEXT("Interrupt initialization failed")); - } - -#if defined(BOARD_EG810MCN_GA_ALIPAY) || defined(BOARD_EG810MCN_GA_VOLTE) - if(vals[4].u_int == 1) { - __fastIntGpio = self->line; - Helios_ExtInt_FastSetGpio(__fastIntGpio); - } else { - if(__fastIntGpio == self->line) { - __fastIntGpio = 0xffff; - Helios_ExtInt_FastSetGpio(__fastIntGpio); - } - } - self->fliter_time = vals[5].u_int; -#else - self->fliter_time = vals[4].u_int; -#endif - - if (self->fliter_time < 0) - { - mp_raise_ValueError(MP_ERROR_TEXT("invalid fliter time value")); - } - - if(self->fliter_time > 0) - { - if(!extint_fliter_timer[self->line]) - { - extint_fliter_timer[self->line] = Helios_OSTimer_Create(); - if (!extint_fliter_timer[self->line]) - { - mp_raise_ValueError(MP_ERROR_TEXT("error: extint fliter timer create failed!")); - } - } - } -#if defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) || defined(PLAT_SONY_ALT1350) - - if(extint_queue == 0) - { - extint_queue = Helios_MsgQ_Create(256, sizeof(extint_Msg)); - if(extint_queue == 0) - { - mp_raise_ValueError(MP_ERROR_TEXT("initialization failed")); - } - } - - if(thread_id == 0) - { - Helios_ThreadAttr ThreadAttr = - { - .name = "machine_extint", - .stack_size = 2048, - .priority = 92, - .entry = extint_entry, - .argv = NULL - }; - thread_id = Helios_Thread_Create(&ThreadAttr); - if(thread_id == 0) - { - mp_raise_ValueError(MP_ERROR_TEXT("initialization failed")); - } - } - -#endif - extint_count_reset(self->line); - return MP_OBJ_FROM_PTR(self); -} - -static void extint_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - extint_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "", self->line); -} - -static mp_obj_t extint_obj_read_count(mp_obj_t self_in, mp_obj_t is_reset) { - extint_obj_t *self = MP_OBJ_TO_PTR(self_in); - int reset_flag = mp_obj_get_int(is_reset); - - if(reset_flag != 0 && reset_flag != 1) { - mp_raise_ValueError(MP_ERROR_TEXT("invalid is_reset value, must in [0,1]")); - } - -#if defined(BOARD_EG810MCN_GA_ALIPAY) || defined(BOARD_EG810MCN_GA_VOLTE) - int count = 0; - if(__fastIntGpio == self->line) { - count += Helios_ExtInt_FastGetCnt(); - if(extint_obj[self->line]->mode == HELIOS_EDGE_RISING){ - extint_count[self->line].rising_count += count; - } else if(extint_obj[self->line]->mode == HELIOS_EDGE_FALLING) { - extint_count[self->line].falling_count += count; - } else { - if(count % 2 == 0) { - extint_count[self->line].rising_count += count / 2; - extint_count[self->line].falling_count += count / 2; - } else { - if(Helios_GPIO_GetLevel(self->line) == 0) { - extint_count[self->line].rising_count++; - } else { - extint_count[self->line].falling_count++; - } - } - } - } -#endif - - mp_obj_t extint_list[2] = { - mp_obj_new_int(extint_count[self->line].rising_count), - mp_obj_new_int(extint_count[self->line].falling_count), - }; - - if(1 == reset_flag) { - extint_count_reset(self->line); - } - return mp_obj_new_list(2, extint_list); -} -static MP_DEFINE_CONST_FUN_OBJ_2(extint_obj_read_count_obj, extint_obj_read_count); - -static mp_obj_t extint_obj_count_reset(mp_obj_t self_in) { - extint_obj_t *self = MP_OBJ_TO_PTR(self_in); - extint_count_reset(self->line); - - return mp_obj_new_int(0); - -} -static MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_count_reset_obj, extint_obj_count_reset); - -static mp_obj_t extint_obj_Deinit(mp_obj_t self_in) { - extint_obj_t *self = MP_OBJ_TO_PTR(self_in); - int ret = -1; - //EXTINT_LOG("extint deinit"); - - extint_obj[self->line] = NULL; - extint_count_reset(self->line); - - if((0 == Helios_ExtInt_Disable((Helios_GPIONum) self->line)) && (0 == Helios_ExtInt_Deinit((Helios_GPIONum) self->line))) { - ret = 0; - } - - return mp_obj_new_int(ret); - -} -static MP_DEFINE_CONST_FUN_OBJ_1(extint__del__obj, extint_obj_Deinit); - -static mp_obj_t extint_obj_read_level(mp_obj_t self_in) { - extint_obj_t *self = MP_OBJ_TO_PTR(self_in); - int ret = -1; - - ret = Helios_GPIO_GetLevel((Helios_GPIONum) self->line); - - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_read_level_obj, extint_obj_read_level); - - -static const mp_rom_map_elem_t extint_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&extint__del__obj) }, - { MP_ROM_QSTR(MP_QSTR_line), MP_ROM_PTR(&extint_obj_line_obj) }, - { MP_ROM_QSTR(MP_QSTR_enable), MP_ROM_PTR(&extint_obj_enable_obj) }, - { MP_ROM_QSTR(MP_QSTR_disable), MP_ROM_PTR(&extint_obj_disable_obj) }, - { MP_ROM_QSTR(MP_QSTR_read_count), MP_ROM_PTR(&extint_obj_read_count_obj) }, - { MP_ROM_QSTR(MP_QSTR_count_reset), MP_ROM_PTR(&extint_obj_count_reset_obj) }, - { MP_ROM_QSTR(MP_QSTR_read_level), MP_ROM_PTR(&extint_obj_read_level_obj)}, - - // class constants - /// \constant IRQ_RISING - interrupt on a rising edge - /// \constant IRQ_FALLING - interrupt on a falling edge - /// \constant IRQ_RISING_FALLING - interrupt on a rising or falling edge - { MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(HELIOS_EDGE_RISING) }, - { MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(HELIOS_EDGE_FALLING) }, - { MP_ROM_QSTR(MP_QSTR_IRQ_RISING_FALLING), MP_ROM_INT(HELIOS_EDGE_BOTH) }, - { MP_ROM_QSTR(MP_QSTR_PULL_DISABLE), MP_ROM_INT(HELIOS_PULL_NONE) }, - { MP_ROM_QSTR(MP_QSTR_PULL_PU), MP_ROM_INT(HELIOS_PULL_UP) }, - { MP_ROM_QSTR(MP_QSTR_PULL_PD), MP_ROM_INT(HELIOS_PULL_DOWN) }, - { MP_ROM_QSTR(MP_QSTR_GPIO0), MP_ROM_INT(HELIOS_GPIO0) }, -#if defined(PLAT_Qualcomm) -#if defined(BOARD_BG95M1) || defined(BOARD_BG95M2) || defined(BOARD_BG95M3) \ - || defined(BOARD_BG95M8) || defined(BOARD_BG95M9) || defined(BOARD_BG95M3_LX) \ - || defined(BOARD_BG95M6) || defined(BOARD_BG95M8_SANX) - { MP_ROM_QSTR(MP_QSTR_GPIO2), MP_ROM_INT(HELIOS_GPIO2) }, - { MP_ROM_QSTR(MP_QSTR_GPIO3), MP_ROM_INT(HELIOS_GPIO3) }, - { MP_ROM_QSTR(MP_QSTR_GPIO6), MP_ROM_INT(HELIOS_GPIO6) }, - { MP_ROM_QSTR(MP_QSTR_GPIO7), MP_ROM_INT(HELIOS_GPIO7) }, - { MP_ROM_QSTR(MP_QSTR_GPIO8), MP_ROM_INT(HELIOS_GPIO8) }, - { MP_ROM_QSTR(MP_QSTR_GPIO9), MP_ROM_INT(HELIOS_GPIO9) }, - { MP_ROM_QSTR(MP_QSTR_GPIO11), MP_ROM_INT(HELIOS_GPIO11) }, - { MP_ROM_QSTR(MP_QSTR_GPIO12), MP_ROM_INT(HELIOS_GPIO12) }, - { MP_ROM_QSTR(MP_QSTR_GPIO14), MP_ROM_INT(HELIOS_GPIO14) }, - { MP_ROM_QSTR(MP_QSTR_GPIO16), MP_ROM_INT(HELIOS_GPIO16) }, - { MP_ROM_QSTR(MP_QSTR_GPIO17), MP_ROM_INT(HELIOS_GPIO17) }, - { MP_ROM_QSTR(MP_QSTR_GPIO18), MP_ROM_INT(HELIOS_GPIO18) }, - { MP_ROM_QSTR(MP_QSTR_GPIO19), MP_ROM_INT(HELIOS_GPIO19) }, - { MP_ROM_QSTR(MP_QSTR_GPIO20), MP_ROM_INT(HELIOS_GPIO20) }, - { MP_ROM_QSTR(MP_QSTR_GPIO21), MP_ROM_INT(HELIOS_GPIO21) }, - - { MP_ROM_QSTR(MP_QSTR_GPIO22), MP_ROM_INT(HELIOS_GPIO22) }, - { MP_ROM_QSTR(MP_QSTR_GPIO23), MP_ROM_INT(HELIOS_GPIO23) }, - { MP_ROM_QSTR(MP_QSTR_GPIO24), MP_ROM_INT(HELIOS_GPIO24) }, - { MP_ROM_QSTR(MP_QSTR_GPIO25), MP_ROM_INT(HELIOS_GPIO25) }, - { MP_ROM_QSTR(MP_QSTR_GPIO26), MP_ROM_INT(HELIOS_GPIO26) }, - { MP_ROM_QSTR(MP_QSTR_GPIO29), MP_ROM_INT(HELIOS_GPIO29) }, - { MP_ROM_QSTR(MP_QSTR_GPIO30), MP_ROM_INT(HELIOS_GPIO30) }, -#elif defined(BOARD_BG77) - { MP_ROM_QSTR(MP_QSTR_GPIO1), MP_ROM_INT(HELIOS_GPIO1) }, - { MP_ROM_QSTR(MP_QSTR_GPIO2), MP_ROM_INT(HELIOS_GPIO2) }, - { MP_ROM_QSTR(MP_QSTR_GPIO4), MP_ROM_INT(HELIOS_GPIO4) }, - { MP_ROM_QSTR(MP_QSTR_GPIO5), MP_ROM_INT(HELIOS_GPIO5) }, - { MP_ROM_QSTR(MP_QSTR_GPIO8), MP_ROM_INT(HELIOS_GPIO8) }, - { MP_ROM_QSTR(MP_QSTR_GPIO10), MP_ROM_INT(HELIOS_GPIO10) }, - { MP_ROM_QSTR(MP_QSTR_GPIO13), MP_ROM_INT(HELIOS_GPIO13) }, - { MP_ROM_QSTR(MP_QSTR_GPIO14), MP_ROM_INT(HELIOS_GPIO14) }, - { MP_ROM_QSTR(MP_QSTR_GPIO17), MP_ROM_INT(HELIOS_GPIO17) }, - { MP_ROM_QSTR(MP_QSTR_GPIO20), MP_ROM_INT(HELIOS_GPIO20) }, - { MP_ROM_QSTR(MP_QSTR_GPIO21), MP_ROM_INT(HELIOS_GPIO21) }, - { MP_ROM_QSTR(MP_QSTR_GPIO22), MP_ROM_INT(HELIOS_GPIO22) }, - { MP_ROM_QSTR(MP_QSTR_GPIO25), MP_ROM_INT(HELIOS_GPIO25) }, - { MP_ROM_QSTR(MP_QSTR_GPIO28), MP_ROM_INT(HELIOS_GPIO28) }, - { MP_ROM_QSTR(MP_QSTR_GPIO31), MP_ROM_INT(HELIOS_GPIO31) }, - { MP_ROM_QSTR(MP_QSTR_GPIO33), MP_ROM_INT(HELIOS_GPIO33) }, - { MP_ROM_QSTR(MP_QSTR_GPIO34), MP_ROM_INT(HELIOS_GPIO34) }, - - { MP_ROM_QSTR(MP_QSTR_GPIO35), MP_ROM_INT(HELIOS_GPIO35) }, - { MP_ROM_QSTR(MP_QSTR_GPIO36), MP_ROM_INT(HELIOS_GPIO36) }, - { MP_ROM_QSTR(MP_QSTR_GPIO39), MP_ROM_INT(HELIOS_GPIO39) }, - { MP_ROM_QSTR(MP_QSTR_GPIO40), MP_ROM_INT(HELIOS_GPIO40) }, - { MP_ROM_QSTR(MP_QSTR_GPIO42), MP_ROM_INT(HELIOS_GPIO42) }, - { MP_ROM_QSTR(MP_QSTR_GPIO43), MP_ROM_INT(HELIOS_GPIO43) }, -#elif defined(BOARD_BG600LM3) - { MP_ROM_QSTR(MP_QSTR_GPIO1), MP_ROM_INT(HELIOS_GPIO1) }, - { MP_ROM_QSTR(MP_QSTR_GPIO2), MP_ROM_INT(HELIOS_GPIO2) }, - { MP_ROM_QSTR(MP_QSTR_GPIO3), MP_ROM_INT(HELIOS_GPIO3) }, - { MP_ROM_QSTR(MP_QSTR_GPIO6), MP_ROM_INT(HELIOS_GPIO6) }, - { MP_ROM_QSTR(MP_QSTR_GPIO7), MP_ROM_INT(HELIOS_GPIO7) }, - { MP_ROM_QSTR(MP_QSTR_GPIO8), MP_ROM_INT(HELIOS_GPIO8) }, - { MP_ROM_QSTR(MP_QSTR_GPIO10), MP_ROM_INT(HELIOS_GPIO10) }, - { MP_ROM_QSTR(MP_QSTR_GPIO11), MP_ROM_INT(HELIOS_GPIO11) }, - { MP_ROM_QSTR(MP_QSTR_GPIO15), MP_ROM_INT(HELIOS_GPIO15) }, - { MP_ROM_QSTR(MP_QSTR_GPIO16), MP_ROM_INT(HELIOS_GPIO16) }, - - { MP_ROM_QSTR(MP_QSTR_GPIO17), MP_ROM_INT(HELIOS_GPIO17) }, - { MP_ROM_QSTR(MP_QSTR_GPIO18), MP_ROM_INT(HELIOS_GPIO18) }, - { MP_ROM_QSTR(MP_QSTR_GPIO19), MP_ROM_INT(HELIOS_GPIO19) }, - { MP_ROM_QSTR(MP_QSTR_GPIO20), MP_ROM_INT(HELIOS_GPIO20) }, - { MP_ROM_QSTR(MP_QSTR_GPIO23), MP_ROM_INT(HELIOS_GPIO23) }, - { MP_ROM_QSTR(MP_QSTR_GPIO25), MP_ROM_INT(HELIOS_GPIO25) }, -#endif -#else -#if !defined(PLAT_ECR6600) - PLAT_GPIO_DEF(PLAT_GPIO_NUM), -#endif -#endif -}; - -static MP_DEFINE_CONST_DICT(extint_locals_dict, extint_locals_dict_table); - -MP_DEFINE_CONST_OBJ_TYPE( - machine_extint_type, - MP_QSTR_ExtInt, - MP_TYPE_FLAG_NONE, - make_new, extint_make_new, - print, extint_obj_print, - locals_dict, &extint_locals_dict - ); -#endif diff --git a/ports/quectel/machine_hw_spi.c b/ports/quectel/machine_hw_spi.c deleted file mode 100644 index 6a6c79460ae5b..0000000000000 --- a/ports/quectel/machine_hw_spi.c +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. - * - * 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. - */ - -#include -#include -#include - -#include "py/runtime.h" -#include "py/gc.h" -#include "py/mphal.h" -#include "py/mperrno.h" -#include "mphalport.h" - -#if MICROPY_QPY_MACHINE_SPI - -#include "helios_spi.h" -#include "helios_debug.h" - - -#define HELIOS_SPI_LOG(msg, ...) custom_log("machine spi", msg, ##__VA_ARGS__) - - -const mp_obj_type_t machine_hard_spi_type; - -typedef struct _machine_hard_spi_obj_t { - mp_obj_base_t base; - uint32_t port; - uint32_t mode; - uint32_t clk; -} machine_hard_spi_obj_t; - -static void machine_hard_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - machine_hard_spi_obj_t *self = self_in; - mp_printf(print, "spi%d", self->port); -} - -mp_obj_t machine_hard_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - enum { ARG_port, ARG_mode, ARG_clk }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_port, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_clk, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - }; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - uint32_t port = args[ARG_port].u_int; - uint32_t mode = args[ARG_mode].u_int; - uint32_t clk = args[ARG_clk].u_int; - int ret=0; - - if (port > HELIOS_SPI3) { - mp_raise_ValueError(MP_ERROR_TEXT("port must be (0~3)")); - } - - if ( mode > 3) { - mp_raise_ValueError(MP_ERROR_TEXT("mode must be (0~3)")); - } - -#if defined(PLAT_Unisoc) - if (clk > 9) { - mp_raise_ValueError(MP_ERROR_TEXT("clk must be (0~9)")); - } -#elif defined(PLAT_RDA) - if (clk > 39) { - mp_raise_ValueError(MP_ERROR_TEXT("clk must be (0~39)")); - } -#elif defined(PLAT_Unisoc_8850) -if (clk > 14) -{ - mp_raise_ValueError(MP_ERROR_TEXT("clk must be (0~14)")); -} -#elif defined(PLAT_SONY_ALT1350) -if (clk > 30) -{ - mp_raise_ValueError(MP_ERROR_TEXT("clk must be (0~30)")); -} -#else - if (clk > 6) { - mp_raise_ValueError(MP_ERROR_TEXT("clk must be (0~6)")); - } -#endif - - - machine_hard_spi_obj_t *self = m_new_obj(machine_hard_spi_obj_t); - - self->base.type = &machine_hard_spi_type; - self->port = port; - self->mode = mode; - self->clk = clk; - - ret = Helios_SPI_Init((Helios_SPINum) self->port, (Helios_SPIMode) self->mode, (uint32_t) self->clk); - if(ret != 0) { - mp_raise_ValueError(MP_ERROR_TEXT("spi init fail")); - } - - HELIOS_SPI_LOG("Helios_SPI_Init %d\r\n",ret); - return MP_OBJ_FROM_PTR(self); -} - -static const mp_arg_t machine_spi_mem_allowed_args[] = { - { MP_QSTR_databuf, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_datasize, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, -}; -static mp_obj_t machine_spi_write_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_databuf, ARG_datasize }; - mp_arg_val_t args[MP_ARRAY_SIZE(machine_spi_mem_allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, - MP_ARRAY_SIZE(machine_spi_mem_allowed_args), machine_spi_mem_allowed_args, args); - - machine_hard_spi_obj_t *self = (machine_hard_spi_obj_t *)MP_OBJ_TO_PTR(pos_args[0]); - - // get the buffer to write the data from - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[ARG_databuf].u_obj, &bufinfo, MP_BUFFER_READ); - - int length = (size_t)args[ARG_datasize].u_int > bufinfo.len ? bufinfo.len : (size_t)args[ARG_datasize].u_int; - // do the transfer - - int ret = Helios_SPI_Write((Helios_SPINum) self->port, (void*) bufinfo.buf, (size_t) length); - if (ret < 0) { - HELIOS_SPI_LOG("Helios_SPI_Write ret=%d\r\n",ret); - mp_raise_OSError(-ret); - } - - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_KW(machine_spi_write_obj, 1, machine_spi_write_mem); - -static mp_obj_t machine_spi_read_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_databuf, ARG_datasize }; - mp_arg_val_t args[MP_ARRAY_SIZE(machine_spi_mem_allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, - MP_ARRAY_SIZE(machine_spi_mem_allowed_args), machine_spi_mem_allowed_args, args); - - machine_hard_spi_obj_t *self = (machine_hard_spi_obj_t *)MP_OBJ_TO_PTR(pos_args[0]); - - // get the buffer to read the data into - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[ARG_databuf].u_obj, &bufinfo, MP_BUFFER_WRITE); - - int length = (size_t)args[ARG_datasize].u_int > bufinfo.len ? bufinfo.len : (size_t)args[ARG_datasize].u_int; - - // do the transfer - int ret = Helios_SPI_Read((Helios_SPINum) self->port, (void*) bufinfo.buf, (size_t) length); - if (ret < 0) { - HELIOS_SPI_LOG("spi read ret=%d\r\n",ret); - mp_raise_OSError(-ret); - } - - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_KW(machine_spi_read_obj, 1, machine_spi_read_mem); -#ifndef PLAT_SONY_ALT1350 -static const mp_arg_t machine_spi_write_read_mem_allowed_args[] = { - { MP_QSTR_readbuf, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_writebuf, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_datasize, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, -}; -static mp_obj_t machine_spi_write_read_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_readbuf, ARG_writebuf, ARG_datasize }; - mp_arg_val_t args[MP_ARRAY_SIZE(machine_spi_write_read_mem_allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, - MP_ARRAY_SIZE(machine_spi_write_read_mem_allowed_args), machine_spi_write_read_mem_allowed_args, args); - - machine_hard_spi_obj_t *self = (machine_hard_spi_obj_t *)MP_OBJ_TO_PTR(pos_args[0]); - - // get the buffer to read the data into - mp_buffer_info_t readbuf; - mp_get_buffer_raise(args[ARG_readbuf].u_obj, &readbuf, MP_BUFFER_WRITE); - mp_buffer_info_t writebuf; - mp_get_buffer_raise(args[ARG_writebuf].u_obj, &writebuf, MP_BUFFER_READ); - - int length = ((size_t)args[ARG_datasize].u_int > readbuf.len ? readbuf.len : (size_t)args[ARG_datasize].u_int); - - - // do the transfer - int ret = Helios_SPI_WriteRead((Helios_SPINum) self->port,(void*) readbuf.buf, (size_t) length,(void*) writebuf.buf,(size_t)args[ARG_datasize].u_int); - - if (ret < 0) { - HELIOS_SPI_LOG("Helios_SPI_WriteRead ret=%d\r\n",ret); - mp_raise_OSError(-ret); - } - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_KW(machine_spi_write_read_obj, 1, machine_spi_write_read_mem); - -#else -static const mp_arg_t machine_spi_half_duplex_write_read_mem_allowed_args[] = { - { MP_QSTR_readbuf, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_writebuf, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_write_datasize, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_read_datasize, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, -}; -static mp_obj_t machine_spi_half_duplex_write_read_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_readbuf, ARG_writebuf, ARG_write_datasize, ARG_read_datasize }; - mp_arg_val_t args[MP_ARRAY_SIZE(machine_spi_half_duplex_write_read_mem_allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, - MP_ARRAY_SIZE(machine_spi_half_duplex_write_read_mem_allowed_args), machine_spi_half_duplex_write_read_mem_allowed_args, args); - - machine_hard_spi_obj_t *self = (machine_hard_spi_obj_t *)MP_OBJ_TO_PTR(pos_args[0]); - - // get the buffer to read the data into - mp_buffer_info_t readbuf; - mp_get_buffer_raise(args[ARG_readbuf].u_obj, &readbuf, MP_BUFFER_WRITE); - mp_buffer_info_t writebuf; - mp_get_buffer_raise(args[ARG_writebuf].u_obj, &writebuf, MP_BUFFER_READ); - - int write_length = ((size_t)args[ARG_write_datasize].u_int > writebuf.len ? writebuf.len : (size_t)args[ARG_write_datasize].u_int); - int read_length = ((size_t)args[ARG_read_datasize].u_int > readbuf.len ? readbuf.len : (size_t)args[ARG_read_datasize].u_int); - - - // do the transfer - int ret = Helios_SPI_WriteRead((Helios_SPINum) self->port,(void*) readbuf.buf, (size_t) read_length,(void*) writebuf.buf,(size_t)write_length); - - if (ret < 0) { - HELIOS_SPI_LOG("Helios_SPI_WriteRead ret=%d\r\n",ret); - mp_raise_OSError(-ret); - } - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_KW(machine_spi_half_duplex_write_read_obj, 1, machine_spi_half_duplex_write_read_mem); -#endif -static const mp_rom_map_elem_t machine_spi_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&machine_spi_read_obj) }, - { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&machine_spi_write_obj) }, -#ifndef PLAT_SONY_ALT1350 - { MP_ROM_QSTR(MP_QSTR_write_read), MP_ROM_PTR(&machine_spi_write_read_obj) }, -#else - { MP_ROM_QSTR(MP_QSTR_half_duplex_write_read), MP_ROM_PTR(&machine_spi_half_duplex_write_read_obj) }, -#endif -#if !defined(BOARD_EC800GCN_GA) - { MP_ROM_QSTR(MP_QSTR_SPI0), MP_ROM_INT(HELIOS_SPI0) }, -#endif -#if !defined(PLAT_RDA) && !defined(BOARD_EG915UEU_AB) - { MP_ROM_QSTR(MP_QSTR_SPI1), MP_ROM_INT(HELIOS_SPI1) }, -#endif -}; - -MP_DEFINE_CONST_DICT(mp_machine_hard_spi_locals_dict, machine_spi_locals_dict_table); - -MP_DEFINE_CONST_OBJ_TYPE( - machine_hard_spi_type, - MP_QSTR_SPI, - MP_TYPE_FLAG_NONE, - make_new, machine_hard_spi_make_new, - print, machine_hard_spi_print, - locals_dict, &mp_machine_hard_spi_locals_dict - ); - -#endif diff --git a/ports/quectel/machine_i2c.h b/ports/quectel/machine_i2c.h deleted file mode 100644 index a3363d4c341c5..0000000000000 --- a/ports/quectel/machine_i2c.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * 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. - */ -#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_I2C_H -#define MICROPY_INCLUDED_EXTMOD_MACHINE_I2C_H - -#include "py/obj.h" -#include "py/mphal.h" - -// Temporary support for legacy construction of SoftI2C via I2C type. -#define MP_MACHINE_I2C_CHECK_FOR_LEGACY_SOFTI2C_CONSTRUCTION(n_args, n_kw, all_args) \ - do { \ - if (n_args == 0 || all_args[0] == MP_OBJ_NEW_SMALL_INT(-1)) { \ - mp_print_str(MICROPY_ERROR_PRINTER, "Warning: I2C(-1, ...) is deprecated, use SoftI2C(...) instead\n"); \ - if (n_args != 0) { \ - --n_args; \ - ++all_args; \ - } \ - return mp_machine_soft_i2c_type.make_new(&mp_machine_soft_i2c_type, n_args, n_kw, all_args); \ - } \ - } while (0) - -#define MP_MACHINE_I2C_FLAG_READ (0x01) // if not set then it's a write -#define MP_MACHINE_I2C_FLAG_STOP (0x02) - -#if MICROPY_PY_MACHINE_I2C_TRANSFER_WRITE1 -// If set, the first mp_machine_i2c_buf_t in a transfer is a write. -#define MP_MACHINE_I2C_FLAG_WRITE1 (0x04) -#endif - -typedef struct _mp_machine_i2c_buf_t { - size_t len; - uint8_t *buf; -} mp_machine_i2c_buf_t; - -// I2C protocol -// - init must be non-NULL -// - start/stop/read/write can be NULL, meaning operation is not supported -// - transfer must be non-NULL -// - transfer_single only needs to be set if transfer=mp_machine_i2c_transfer_adaptor -typedef struct _mp_machine_i2c_p_t { - #if MICROPY_PY_MACHINE_I2C_TRANSFER_WRITE1 - bool transfer_supports_write1; - #endif - void (*init)(mp_obj_base_t *obj, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); - int (*start)(mp_obj_base_t *obj); - int (*stop)(mp_obj_base_t *obj); - int (*read)(mp_obj_base_t *obj, uint8_t *dest, size_t len, bool nack); - int (*write)(mp_obj_base_t *obj, const uint8_t *src, size_t len); - int (*transfer)(mp_obj_base_t *obj, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags); - int (*transfer_single)(mp_obj_base_t *obj, uint16_t addr, size_t len, uint8_t *buf, unsigned int flags); -} mp_machine_i2c_p_t; - -typedef struct _mp_machine_soft_i2c_obj_t { - mp_obj_base_t base; - uint32_t us_delay; - uint32_t us_timeout; - mp_hal_pin_obj_t scl; - mp_hal_pin_obj_t sda; -} mp_machine_soft_i2c_obj_t; - -extern const mp_obj_type_t mp_machine_soft_i2c_type; -extern const mp_obj_dict_t mp_machine_i2c_locals_dict; - -int mp_machine_i2c_transfer_adaptor(mp_obj_base_t *self, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags); -int mp_machine_soft_i2c_transfer(mp_obj_base_t *self, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags); - -#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_I2C_H diff --git a/ports/quectel/machine_iic.c b/ports/quectel/machine_iic.c deleted file mode 100644 index 8cd9408fae2e6..0000000000000 --- a/ports/quectel/machine_iic.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020-2021 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 "py/gc.h" -#include "py/mphal.h" -#include "py/mperrno.h" - -#if MICROPY_QPY_MACHINE_I2C - -#include "machine_i2c.h" -#include "helios_iic.h" -#include "mphalport.h" - - -const mp_obj_type_t machine_hard_i2c_type; - -typedef struct _machine_hard_i2c_obj_t { - mp_obj_base_t base; - uint32_t bus_id; - uint32_t fastmode; -} machine_hard_i2c_obj_t; - -static void machine_hard_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - machine_hard_i2c_obj_t *self = self_in; - mp_printf(print, "I2C%d", self->bus_id); -} - -mp_obj_t machine_hard_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - enum { ARG_id, ARG_fastmode }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_fastmode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 1} }, - }; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - uint32_t bus_id = args[ARG_id].u_int; - uint32_t fastmode = args[ARG_fastmode].u_int; - - - if (bus_id > HELIOS_I2C3) { - mp_raise_ValueError(MP_ERROR_TEXT("bus id must be (0~3)")); - } - - volatile machine_hard_i2c_obj_t *self = m_new_obj(machine_hard_i2c_obj_t); - - self->base.type = &machine_hard_i2c_type; - self->bus_id = bus_id; - self->fastmode = fastmode; - if(0 != Helios_I2C_Init((Helios_I2CEnum) self->bus_id, (Helios_I2CMode) self->fastmode)) { - return mp_const_false; - } - return MP_OBJ_FROM_PTR(self); -} -static const mp_arg_t machine_i2c_mem_allowed_args[] = { - { MP_QSTR_slaveaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_regaddr, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_regaddr_len, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_databuf, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_datasize, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 8} }, -}; -static mp_obj_t machine_i2c_write_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_slaveaddr, ARG_regaddr, ARG_regaddr_len, ARG_databuf, ARG_datasize }; - mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, - MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args); - - machine_hard_i2c_obj_t *self = (machine_hard_i2c_obj_t *)MP_OBJ_TO_PTR(pos_args[0]); - - mp_buffer_info_t regaddr_bufinfo; - mp_get_buffer_raise(args[ARG_regaddr].u_obj, ®addr_bufinfo, MP_BUFFER_READ); - int regaddr_length = args[ARG_regaddr_len].u_int; - - // get the buffer to write the data from - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[ARG_databuf].u_obj, &bufinfo, MP_BUFFER_READ); - int length = (size_t)args[ARG_datasize].u_int > bufinfo.len ? bufinfo.len : (size_t)args[ARG_datasize].u_int; - //uart_printf("i2c wirte: busid:%x slaveddr:%x, regaddr:%x, data:%s datalen:%d\n", self->bus_id, args[ARG_slaveaddr].u_int, args[ARG_regaddr].u_int, - // bufinfo.buf, args[ARG_datasize].u_int); - // do the transfer - int ret = HELIOS_I2C_Write((Helios_I2CEnum) self->bus_id, (uint8_t) args[ARG_slaveaddr].u_int, (uint8_t*) regaddr_bufinfo.buf,(size_t) regaddr_length,(void*) bufinfo.buf, (size_t) length); - if (ret < 0) { - ret = -1; - return mp_obj_new_int(ret); - } - - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_write_obj, 1, machine_i2c_write_mem); - -static const mp_arg_t machine_i2c_mem_allowed_read_args[] = { - { MP_QSTR_slaveaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_regaddr, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_regaddr_len, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_databuf, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_datasize, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 8} }, - { MP_QSTR_dalay, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 8} }, -}; -static mp_obj_t machine_i2c_read_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_slaveaddr, ARG_regaddr, ARG_regaddr_len, ARG_databuf, ARG_datasize, ARG_dalay }; - mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_read_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, - MP_ARRAY_SIZE(machine_i2c_mem_allowed_read_args), machine_i2c_mem_allowed_read_args, args); - - machine_hard_i2c_obj_t *self = (machine_hard_i2c_obj_t *)MP_OBJ_TO_PTR(pos_args[0]); - - mp_buffer_info_t regaddr_bufinfo; - mp_get_buffer_raise(args[ARG_regaddr].u_obj, ®addr_bufinfo, MP_BUFFER_READ); - int regaddr_length = (size_t)args[ARG_regaddr_len].u_int > regaddr_bufinfo.len ? regaddr_bufinfo.len : (size_t)args[ARG_regaddr_len].u_int; - - // get the buffer to read the data into - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[ARG_databuf].u_obj, &bufinfo, MP_BUFFER_WRITE); - - int length = (size_t)args[ARG_datasize].u_int > bufinfo.len ? bufinfo.len : (size_t)args[ARG_datasize].u_int; - - //uart_printf("i2c read: busid:%x slaveddr:%x, regaddr:%x, datalen:%d\n", self->bus_id, args[ARG_slaveaddr].u_int, args[ARG_regaddr].u_int, - // args[ARG_datasize].u_int); - // do the transfer - int ret = HELIOS_I2C_Read((Helios_I2CEnum) self->bus_id, (uint8_t) args[ARG_slaveaddr].u_int,(uint8_t*) regaddr_bufinfo.buf, (size_t) regaddr_length, (void*) bufinfo.buf, (size_t) length,(uint32_t) args[ARG_dalay].u_int); - if (ret < 0) { - ret = -1; - return mp_obj_new_int(ret); - } - - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_read_obj, 1, machine_i2c_read_mem); - -static const mp_rom_map_elem_t machine_i2c_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&machine_i2c_read_obj) }, - { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&machine_i2c_write_obj) }, - // class constants - { MP_ROM_QSTR(MP_QSTR_I2C0), MP_ROM_INT(HELIOS_I2C0) }, -#if !defined(PLAT_ASR_1803s) && !defined(BOARD_EC800MCN_LA) && !defined(BOARD_EC800MCN_GA) && !defined(BOARD_EC800NCN_LA) && !defined(BOARD_EC800NCN_LA_VOLTE) - { MP_ROM_QSTR(MP_QSTR_I2C1), MP_ROM_INT(HELIOS_I2C1) }, -#endif -#if !defined(PLAT_RDA) && !defined(BOARD_EC800NCN_LA) && !defined(BOARD_EC800NCN_LA_VOLTE) && !defined(BOARD_EC600GCN_LD) - { MP_ROM_QSTR(MP_QSTR_I2C2), MP_ROM_INT(HELIOS_I2C2) }, -#if !defined(PLAT_Qualcomm) && !defined(BOARD_EC800MCN_LA) && !defined(BOARD_EC800MCN_GA) && !defined(BOARD_EC800GCN_GA) && !defined(BOARD_EC800GCN_LD) && !defined(BOARD_EC800GCN_LD_HRXM) - { MP_ROM_QSTR(MP_QSTR_I2C3), MP_ROM_INT(HELIOS_I2C3) }, -#endif -#endif - { MP_ROM_QSTR(MP_QSTR_STANDARD_MODE), MP_ROM_INT(HELIOS_STANDARD_MODE) }, - { MP_ROM_QSTR(MP_QSTR_FAST_MODE), MP_ROM_INT(HELIOS_FAST_MODE) }, -}; - -MP_DEFINE_CONST_DICT(mp_machine_hard_i2c_locals_dict, machine_i2c_locals_dict_table); - - -MP_DEFINE_CONST_OBJ_TYPE( - machine_hard_i2c_type, - MP_QSTR_I2C, - MP_TYPE_FLAG_NONE, - make_new, machine_hard_i2c_make_new, - print, machine_hard_i2c_print, - locals_dict, &mp_machine_hard_i2c_locals_dict - ); - -#endif diff --git a/ports/quectel/machine_pin.c b/ports/quectel/machine_pin.c deleted file mode 100644 index b9953c9f774c1..0000000000000 --- a/ports/quectel/machine_pin.c +++ /dev/null @@ -1,333 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020-2021 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 "py/gc.h" -#include "py/mphal.h" - -#if MICROPY_QPY_MACHINE_PIN - -#include "helios_gpio.h" -#include "helios_debug.h" - - -#define HELIOS_PIN_LOG(msg, ...) custom_log("machine_pin", msg, ##__VA_ARGS__) - -#define GPIO_OBJ_DEF(n) {{&machine_pin_type}, HELIOS_GPIO##n, 0, 0, 0} -#define PLAT_GPIO_OBJ_DEF(n) BOOST_PP_REPEAT_1(n,GPIO_OBJ_DEF) - - -typedef struct _machine_pin_obj_t { - mp_obj_base_t base; - uint pin; - uint dir; - uint pull; - uint value; -} machine_pin_obj_t; - -const mp_obj_type_t machine_pin_type; - - -static machine_pin_obj_t *machine_pin_obj[PLAT_GPIO_NUM] = {NULL}; - - -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, "", self->pin); -} - -// pin.init(mode, pull=None, *, value) -static mp_obj_t machine_pin_obj_init_helper(machine_pin_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_dir, ARG_pull, ARG_value }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_dir, MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_pull, MP_ARG_INT, {.u_int = -1}}, - { MP_QSTR_value, MP_ARG_INT, {.u_int = -1}}, - }; - - // 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); - - // get dir mode - switch (args[ARG_dir].u_int) { - case -1: - break; - case HELIOS_GPIO_INPUT: - case HELIOS_GPIO_OUTPUT: - self->dir = args[ARG_dir].u_int; - break; - default: - mp_raise_ValueError(MP_ERROR_TEXT("invalid pin dir, range{0:dir in, 1:dir out}")); - break; - } - // get pull mode - switch (args[ARG_pull].u_int) { - case -1: - break; - case HELIOS_PULL_NONE: - case HELIOS_PULL_UP: - case HELIOS_PULL_DOWN: - self->pull = args[ARG_pull].u_int; - break; - default: - mp_raise_ValueError(MP_ERROR_TEXT("invalid pin pull, range{0:PIN_PULL_DISABLE, 1:PIN_PULL_PU, 2:PIN_PULL_PD}")); - break; - } - // get initial value - switch (args[ARG_value].u_int) { - case -1: - break; - case HELIOS_LVL_LOW: - case HELIOS_LVL_HIGH: - self->value = args[ARG_value].u_int; - break; - default: - mp_raise_ValueError(MP_ERROR_TEXT("invalid pin value, range{0:PIN_LEVEL_LOW, 1:PIN_LEVEL_HIGH}")); - break; - } - Helios_GPIOInitStruct gpio_struct = {0}; - gpio_struct.dir = self->dir; - gpio_struct.pull = self->pull; - gpio_struct.value = self->value; - HELIOS_PIN_LOG("pin = %d dir = %d, pull = %d value=%d\n",self->pin, self->dir, self->pull, self->value); - int ret = Helios_GPIO_Init((Helios_GPIONum) self->pin, &gpio_struct); - HELIOS_PIN_LOG("gpio init ret = %d\n",ret); - - if (ret != 0){ - mp_raise_ValueError(MP_ERROR_TEXT("GPIO initialization error")); - } - - - return mp_const_none; -} - -// constructor(drv_name, pin, ...) -mp_obj_t mp_pin_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, MP_OBJ_FUN_ARGS_MAX, true); - - // get the wanted pin object - //unsigned int i = 0; - int wanted_pin = 0; - wanted_pin = mp_obj_get_int(args[0]); - - if(wanted_pin == 0 || wanted_pin > PLAT_GPIO_NUM) { - mp_raise_ValueError(MP_ERROR_TEXT("invalid pin")); - } - - HELIOS_PIN_LOG("wanted_pin = %d\n",wanted_pin); - machine_pin_obj_t *self = NULL; - - if (machine_pin_obj[wanted_pin-1] == NULL) - { - machine_pin_obj[wanted_pin-1] = mp_obj_malloc_with_finaliser(machine_pin_obj_t, &machine_pin_type); - } - self = machine_pin_obj[wanted_pin-1]; - self->base.type = &machine_pin_type; - self->pin = wanted_pin; - - // default settings - self->dir = HELIOS_GPIO_OUTPUT; - self->pull = HELIOS_PULL_NONE; - self->value = HELIOS_LVL_LOW; - HELIOS_PIN_LOG("dir = %d, pull = %d value=%d\n",self->dir, self->pull, self->value); - - if (n_args > 1 || n_kw > 0) { - // pin mode given, so configure this GPIO - mp_map_t kw_args; - mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); - HELIOS_PIN_LOG("n_args = %d\n",n_args); - machine_pin_obj_init_helper(self, n_args - 1, args + 1, &kw_args); - HELIOS_PIN_LOG("n_kw = %d\n",n_kw); - } else { - - Helios_GPIOInitStruct gpio_struct = {0}; - gpio_struct.dir = self->dir; - gpio_struct.pull = self->pull; - gpio_struct.value = self->value; - Helios_GPIO_Init((Helios_GPIONum) self->pin, &gpio_struct); - } - - HELIOS_PIN_LOG("pin init end\n"); - return MP_OBJ_FROM_PTR(self); -} - -// fast method for getting/setting pin value -static mp_obj_t machine_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 0, 1, false); - machine_pin_obj_t *self = self_in; - if (n_args == 0) { - int pin_val = Helios_GPIO_GetLevel((Helios_GPIONum) self->pin); - return MP_OBJ_NEW_SMALL_INT(pin_val); - } else { - Helios_GPIO_SetLevel((Helios_GPIONum) self->pin, (Helios_LvlMode) mp_obj_is_true(args[0])); - return mp_const_none; - } -} - -// pin.init(mode, pull) -static mp_obj_t machine_pin_obj_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { - return machine_pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args); -} -MP_DEFINE_CONST_FUN_OBJ_KW(machine_pin_init_obj, 1, machine_pin_obj_init); - -// pin.value([value]) -static mp_obj_t machine_pin_value(size_t n_args, const mp_obj_t *args) { - return machine_pin_call(args[0], n_args - 1, 0, args + 1); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_value_obj, 1, 2, machine_pin_value); - -static mp_obj_t machine_pin_off(mp_obj_t self_in) { - machine_pin_obj_t *self = self_in; - Helios_GPIO_SetLevel((Helios_GPIONum) self->pin, (Helios_LvlMode) HELIOS_LVL_LOW); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_off_obj, machine_pin_off); - -static mp_obj_t machine_pin_on(mp_obj_t self_in) { - machine_pin_obj_t *self = self_in; - Helios_GPIO_SetLevel((Helios_GPIONum) self->pin, (Helios_LvlMode) HELIOS_LVL_HIGH); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_on_obj, machine_pin_on); - -static mp_obj_t machine_pin_write(mp_obj_t self_in, mp_obj_t value) -{ - machine_pin_obj_t *self = self_in; - int pin_value = mp_obj_get_int(value); - int ret = Helios_GPIO_SetLevel((Helios_GPIONum) self->pin, (Helios_LvlMode) pin_value); - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_2(machine_pin_write_obj, machine_pin_write); - -static mp_obj_t machine_pin_read(size_t n_args, const mp_obj_t *args) -{ - return machine_pin_call(args[0], n_args - 1, 0, args + 1); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_read_obj, 1, 2, machine_pin_read); - - -static mp_uint_t machine_pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { - (void)errcode; - machine_pin_obj_t *self = self_in; - - switch (request) { - case MP_PIN_READ: { - int pin_val = Helios_GPIO_GetLevel((Helios_GPIONum) self->pin); - return pin_val; - } - case MP_PIN_WRITE: { - Helios_GPIO_SetLevel((Helios_GPIONum) self->pin, (Helios_LvlMode) arg); - return 0; - } - } - return -1; -} - -static mp_obj_t machine_pin_set_dir(mp_obj_t self_in, mp_obj_t dir) -{ - machine_pin_obj_t *self = self_in; - int ret = -1; - - int pin_value = mp_obj_get_int(dir); - if((pin_value != HELIOS_GPIO_INPUT) && (pin_value != HELIOS_GPIO_OUTPUT)){ - mp_raise_ValueError(MP_ERROR_TEXT("Invalid direction parameter")); - } - ret = Helios_GPIO_SetDirection((Helios_GPIONum) self->pin, (Helios_GPIODir) pin_value); - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_2(machine_pin_set_dir_obj, machine_pin_set_dir); - -static mp_obj_t machine_pin_get_dir(mp_obj_t self_in) -{ - machine_pin_obj_t *self = self_in; - int ret = Helios_GPIO_GetDirection((Helios_GPIONum) self->pin); - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_get_dir_obj, machine_pin_get_dir); - - -static mp_obj_t machine_pin_deinit(mp_obj_t self_in) { - machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in); - //HELIOS_PIN_LOG("machine pin deinit.pin=%d.\r\n", self->pin); - - machine_pin_obj[self->pin - 1] = NULL; - - int ret = Helios_GPIO_Deinit((Helios_GPIONum)self->pin); - if (ret != 0) - { - HELIOS_PIN_LOG("GPIO%d deinit failed.\r\n", self->pin); - } - return mp_obj_new_int(ret); - -} -static MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_deinit_obj, machine_pin_deinit); - - -static const mp_rom_map_elem_t machine_pin_locals_dict_table[] = { - // instance methods - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&machine_pin_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_pin_init_obj) }, - { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&machine_pin_value_obj) }, - { MP_ROM_QSTR(MP_QSTR_off), MP_ROM_PTR(&machine_pin_off_obj) }, - { MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&machine_pin_on_obj) }, - { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&machine_pin_write_obj) }, - { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&machine_pin_read_obj) }, - { MP_ROM_QSTR(MP_QSTR_set_dir), MP_ROM_PTR(&machine_pin_set_dir_obj) }, - { MP_ROM_QSTR(MP_QSTR_get_dir), MP_ROM_PTR(&machine_pin_get_dir_obj) }, - // class constants - //GPIO DEFINE - { MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(HELIOS_GPIO_INPUT) }, - { MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(HELIOS_GPIO_OUTPUT) }, - { MP_ROM_QSTR(MP_QSTR_PULL_PU), MP_ROM_INT(HELIOS_PULL_UP) }, - { MP_ROM_QSTR(MP_QSTR_PULL_PD), MP_ROM_INT(HELIOS_PULL_DOWN) }, - { MP_ROM_QSTR(MP_QSTR_PULL_DISABLE), MP_ROM_INT(HELIOS_PULL_NONE) }, - PLAT_GPIO_DEF(PLAT_GPIO_NUM), -}; - -static MP_DEFINE_CONST_DICT(machine_pin_locals_dict, machine_pin_locals_dict_table); - -static const mp_pin_p_t machine_pin_pin_p = { - .ioctl = machine_pin_ioctl, -}; - -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, &machine_pin_pin_p, - locals_dict, &machine_pin_locals_dict - ); - -#endif - diff --git a/ports/quectel/machine_rtc.c b/ports/quectel/machine_rtc.c deleted file mode 100644 index 720e6c0a3d6fc..0000000000000 --- a/ports/quectel/machine_rtc.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020-2021 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/nlr.h" -#include "py/obj.h" -#include "py/runtime.h" -#include "py/mphal.h" - -#if MICROPY_QPY_MACHINE_RTC - -#include "modmachine.h" -#include "helios_debug.h" -#include "helios_rtc.h" -#include "callbackdeal.h" - -#define HELIOS_RTC_LOG(fmt, ...) custom_log(machine_rtc, fmt, ##__VA_ARGS__) - - -typedef struct _machine_rtc_obj_t { - mp_obj_base_t base; -} machine_rtc_obj_t; - -static c_callback_t *callback_cur = NULL; - - -// singleton RTC object -//static const machine_rtc_obj_t machine_rtc_obj = {{&machine_rtc_type}}; -const mp_obj_type_t machine_rtc_type; -static machine_rtc_obj_t *machine_rtc_obj_ptr = NULL; - - - -static mp_obj_t machine_rtc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - // check arguments - mp_arg_check_num(n_args, n_kw, 0, 0, false); - if (machine_rtc_obj_ptr != NULL) - { - // singleton RTC object - return MP_OBJ_FROM_PTR(machine_rtc_obj_ptr); - } - machine_rtc_obj_ptr = mp_obj_malloc_with_finaliser(machine_rtc_obj_t, &machine_rtc_type); - machine_rtc_obj_ptr->base.type = &machine_rtc_type; - return MP_OBJ_FROM_PTR(machine_rtc_obj_ptr); -} - - - -static mp_obj_t machine_rtc_datetime_helper(mp_uint_t n_args, const mp_obj_t *args) { - //ql_rtc_time_t tm = {0}; //Jayceon-2020/08/27:Resolved that calling the init() function would cause system dump - Helios_RTCTime tm = {0}; - if (n_args == 1) { - // Pawn 2021/4/28 Solve the problem of different initial time zones between RDA and ASR - // Pawn Fix the bug SW1PQUECPYTHON-119 - Helios_RTC_GetLocalTime(&tm); - // Pawn Fix the bug SW1PQUECPYTHON-119 end - 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_wday), - 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(0) - }; - - return mp_obj_new_tuple(8, tuple); - } else { - // Set time - - mp_obj_t *items; - mp_obj_get_array_fixed_n(args[1], 8, &items); - tm.tm_year = mp_obj_get_int(items[0]); - tm.tm_mon = mp_obj_get_int(items[1]); - tm.tm_mday = mp_obj_get_int(items[2]); - tm.tm_hour = mp_obj_get_int(items[4]); - tm.tm_min = mp_obj_get_int(items[5]); - tm.tm_sec = mp_obj_get_int(items[6]); - - //int ret = ql_rtc_set_time(&tm); - - // Pawn Fix the bug SW1PQUECPYTHON-119 - int ret = Helios_RTC_NtpSetTime(&tm, 1); - // Pawn Fix the bug SW1PQUECPYTHON-119 end - - return mp_obj_new_int(ret); - } -} - - -static mp_obj_t machine_rtc_datetime(mp_uint_t n_args, const mp_obj_t *args) { - return machine_rtc_datetime_helper(n_args, args); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_rtc_datetime_obj, 1, 2, (mp_obj_t)machine_rtc_datetime); - -#if !defined(PLAT_Qualcomm) -static mp_obj_t machine_rtc_set_alarm(mp_obj_t self_in, mp_obj_t time) -{ - Helios_RTCTime tm = {0}; - mp_obj_t *items; - - mp_obj_get_array_fixed_n(time, 8, &items); - tm.tm_year = mp_obj_get_int(items[0]); - tm.tm_mon = mp_obj_get_int(items[1]); - tm.tm_mday = mp_obj_get_int(items[2]); - tm.tm_hour = mp_obj_get_int(items[4]); - tm.tm_min = mp_obj_get_int(items[5]); - tm.tm_sec = mp_obj_get_int(items[6]); - - int ret = Helios_RTC_Set_Alarm(&tm); - - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_2(machine_rtc_set_alarm_obj, machine_rtc_set_alarm); - - -static mp_obj_t machine_rtc_enable_alarm(mp_obj_t self_in, mp_obj_t enable) -{ - int on_off = mp_obj_get_int(enable); - - int ret = Helios_RTC_Enable_Alarm((unsigned char)on_off); - - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_2(machine_rtc_enable_alarm_obj, machine_rtc_enable_alarm); - - -void rtc_callback_to_python(void) -{ - if(callback_cur == NULL) { - return; - } - - mp_sched_schedule_ex(callback_cur, mp_const_none); - -#if defined(PLAT_RDA) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) - Helios_Rtc_Set_Called(Helios_Rtc_Call_NoCalled); -#endif -} - - -static mp_obj_t machine_rtc_register_callback(mp_obj_t self_in, mp_obj_t callback) -{ - static c_callback_t cb = {0}; - memset(&cb, 0, sizeof(c_callback_t)); - callback_cur = &cb; - mp_sched_schedule_callback_register(callback_cur, callback); - -#if defined(PLAT_RDA) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) - if ( Helios_Rtc_Get_Called() == Helios_Rtc_Call_Called ) - { - mp_sched_schedule_ex(callback_cur, NULL); - Helios_Rtc_Set_Called(Helios_Rtc_Call_NoCalled); - } -#endif - int ret = Helios_RTC_Register_cb(rtc_callback_to_python); - - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_2(machine_rtc_register_callback_obj, machine_rtc_register_callback); -#endif - -static mp_obj_t machine_rtc_init(mp_obj_t self_in, mp_obj_t date) { - mp_obj_t args[2] = {self_in, date}; - machine_rtc_datetime_helper(2, args); - - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_2(machine_rtc_init_obj, machine_rtc_init); - -static mp_obj_t machine_rtc_deinit(mp_obj_t self_in) { - HELIOS_RTC_LOG("machine rtc deinit.\r\n"); - callback_cur = NULL; - machine_rtc_obj_ptr = NULL; - return mp_obj_new_int(0); -} -static MP_DEFINE_CONST_FUN_OBJ_1(machine_rtc_deinit_obj, machine_rtc_deinit); - - -static const mp_rom_map_elem_t machine_rtc_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_rtc_init_obj) }, - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&machine_rtc_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR_datetime), MP_ROM_PTR(&machine_rtc_datetime_obj) }, -#if !defined(PLAT_Qualcomm) - { MP_ROM_QSTR(MP_QSTR_set_alarm), MP_ROM_PTR(&machine_rtc_set_alarm_obj) }, - { MP_ROM_QSTR(MP_QSTR_enable_alarm), MP_ROM_PTR(&machine_rtc_enable_alarm_obj) }, - { MP_ROM_QSTR(MP_QSTR_register_callback), MP_ROM_PTR(&machine_rtc_register_callback_obj) }, -#endif -}; -static MP_DEFINE_CONST_DICT(machine_rtc_locals_dict, machine_rtc_locals_dict_table); - -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 - ); - -#endif /* MICROPY_QPY_MACHINE_RTC */ - diff --git a/ports/quectel/machine_timer.c b/ports/quectel/machine_timer.c deleted file mode 100644 index 01e9d153305f3..0000000000000 --- a/ports/quectel/machine_timer.c +++ /dev/null @@ -1,311 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020-2021 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/obj.h" -#include "py/runtime.h" -#include "modmachine.h" -#include "mphalport.h" - - -#if MICROPY_QPY_MACHINE_TIMER - -#include "helios_timer.h" -#include "helios_debug.h" -#include "callbackdeal.h" - - -typedef unsigned long int UINT32; -#define HELIOS_TIMER_LOG(msg, ...) custom_log("machine_timer", msg, ##__VA_ARGS__) - - -typedef enum -{ - Timer0 = 0, - Timer1 = 1, - Timer2 = 2, - Timer3 = 3 -}Timern; - -typedef enum /* The meaning of the API flag*/ -{ - TIMER_PERIODIC = 0x1, /* periodic execution */ - TIMER_AUTO_DELETE = 0x2 /* one execution */ -}TIMER_FLAG; - -typedef enum -{ - MP_TIMER_CREATED, - MP_TIMER_RUNNING, - MP_TIMER_STOP -}MP_TIMER_STATUS; - -typedef struct _machine_timer_obj_t { - mp_obj_base_t base; - //ONE_SHOT OR PERIODIC - mp_uint_t mode; - mp_uint_t period; - c_callback_t callback; - mp_int_t timer_id; - mp_int_t timer_id_real; - MP_TIMER_STATUS timer_status; - //for traverse all the timers, such as soft reset while input CTRL+B - struct _machine_timer_obj_t *next; -} machine_timer_obj_t; - -static void machine_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - (void)(print); - (void)(kind); - machine_timer_obj_t *self = self_in; - HELIOS_TIMER_LOG("period=%d\r\n", self->period); - HELIOS_TIMER_LOG("timer_id=%d\r\n", self->timer_id); -} - -#if defined(BOARD_BC32RA) || defined(BOARD_BC92RB) || defined(PLAT_SONY_ALT1350)//forrest.liu@20231228 add for FAE-102027 dump issue -#define HELIOS_TIMER_MAX_NUM (4) -static st_CallBack_Timer Timer_t[HELIOS_TIMER_MAX_NUM] = {{{0,0,0,0,0}},{{0,0,0,0,0}},{{0,0,0,0,0}},{{0,0,0,0,0}}}; -#endif - -static void machine_timer_isr(UINT32 self_in) { - - machine_timer_obj_t *self = (void*)self_in; - if(self != NULL) - { - #if defined(BOARD_BC32RA) || defined(BOARD_BC92RB) || defined(PLAT_SONY_ALT1350)//forrest.liu@20231228 modify for FAE-102027 dump issue - Timer_t[self->timer_id].callback = self->callback; - qpy_send_msg_to_callback_deal_thread(CALLBACK_TYPE_ID_TIMER, &Timer_t[self->timer_id]); - #else - mp_sched_schedule_ex(&self->callback, self); - #endif - } - -} - - -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) { - 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 = TIMER_PERIODIC} }, - { MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { 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} }, - #if MICROPY_PY_BUILTINS_FLOAT - { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - #else - { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} }, - #endif - }; - - int ret; - - 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 MICROPY_PY_BUILTINS_FLOAT - if (args[ARG_freq].u_obj != mp_const_none) { - self->period = (mp_uint_t)(1000 / mp_obj_get_float(args[ARG_freq].u_obj)); - } - #else - if (args[ARG_freq].u_int != 0xffffffff) { - self->period = 1000 / ((mp_uint_t)args[ARG_freq].u_int); - } - #endif - else { - self->period = (((uint64_t)args[ARG_period].u_int) * 1000) / args[ARG_tick_hz].u_int; - } - - self->mode = args[ARG_mode].u_int; - - mp_sched_schedule_callback_register(&self->callback, args[ARG_callback].u_obj); - - HELIOS_TIMER_LOG("mode: %d, period: %d,callback:%#X\r\n", self->mode, self->period,self->callback.cb); - -// Check whether the timer is already running, if so return 0 - if (MP_TIMER_RUNNING == self->timer_status) { - return mp_obj_new_int(0); - } - - int timer = 0; - if(0 == self->timer_id_real) - { - - if(!self) - { - HELIOS_TIMER_LOG("timer test 147!\n"); - } - HELIOS_TIMER_LOG("self = %x\n",self); - timer = Helios_Timer_init( (void* )machine_timer_isr, self); - } - else - { - HELIOS_TIMER_LOG("timer test 153!\n"); - timer = self->timer_id_real; - } - - if(!timer) { - return mp_const_false; - } - - uint8_t cyclicalEn = 0; - if(self->mode == TIMER_PERIODIC) { - cyclicalEn = 1; - } - HELIOS_TIMER_LOG("timer test 165!\n"); - ret = Helios_Timer_Start(timer, (uint32_t) self->period, cyclicalEn); - HELIOS_TIMER_LOG("timer test 167!\n"); - - if(!ret) - { - //get time_id_real - HELIOS_TIMER_LOG("timer_id: %#x\r\n", timer); - self->timer_id_real = timer; - self->timer_status = MP_TIMER_RUNNING; - } - else - { - HELIOS_TIMER_LOG("timer create failed.ret=%d\r\n",ret); - } - return mp_obj_new_int(0); -} - - - -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) { - (void)(type); - mp_int_t timer_id=0; - - if (n_args > 0) { - timer_id = mp_obj_get_int(args[0]); - --n_args; - ++args; - } - - if ((timer_id < 0) || (timer_id > 3)) - { - mp_raise_ValueError(MP_ERROR_TEXT("invalid value, Timern should be in (Timer0~Timer3).")); - } - - machine_timer_obj_t *self = m_new_obj(machine_timer_obj_t); - self->base.type = &machine_timer_type; - self->timer_id = timer_id; - self->timer_id_real = 0; - self->timer_status = MP_TIMER_CREATED; - - 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]); - - 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_stop(mp_obj_t self_in) { - machine_timer_obj_t *self = MP_OBJ_TO_PTR(self_in); - - if(self->timer_id_real) - { - HELIOS_TIMER_LOG("machine_timer_stop (%#X) \r\n",self->timer_id_real); - Helios_Timer_Stop(self->timer_id_real); - self->timer_status = MP_TIMER_STOP; - return mp_obj_new_int(0); - } - return mp_obj_new_int(-1); -} - -static MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_stop_obj, machine_timer_stop); - - -static mp_obj_t machine_timer_deinit(mp_obj_t self_in) { - machine_timer_obj_t *self = MP_OBJ_TO_PTR(self_in); - - if(self->timer_id_real) - { - HELIOS_TIMER_LOG("machine_timer_deinit (%#X) \r\n",self->timer_id_real); - Helios_Timer_Stop(self->timer_id_real); - Helios_Timer_Deinit(self->timer_id_real); - self->timer_id_real = 0; - self->timer_status = MP_TIMER_STOP; - return mp_obj_new_int(0); - } - return mp_obj_new_int(-1); -} - -static MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_deinit_obj, machine_timer_deinit); - - -static mp_obj_t machine_timer_initialize() { - static int initialized = 0; - if (!initialized) { - - HELIOS_TIMER_LOG("machine_timer_initialize\r\n"); - initialized = 1; - } - return mp_const_none; -} - -static MP_DEFINE_CONST_FUN_OBJ_0(machine_timer_initialize_obj, machine_timer_initialize); - -static const mp_rom_map_elem_t machine_timer_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&machine_timer_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&machine_timer_initialize_obj) }, - { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&machine_timer_stop_obj) }, - { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&machine_timer_init_obj) }, - { MP_ROM_QSTR(MP_QSTR_ONE_SHOT), MP_ROM_INT(TIMER_AUTO_DELETE) }, - { MP_ROM_QSTR(MP_QSTR_PERIODIC), MP_ROM_INT(TIMER_PERIODIC) }, - { MP_ROM_QSTR(MP_QSTR_Timer0), MP_ROM_INT(Timer0) }, - { MP_ROM_QSTR(MP_QSTR_Timer1), MP_ROM_INT(Timer1) }, - { MP_ROM_QSTR(MP_QSTR_Timer2), MP_ROM_INT(Timer2) }, - { MP_ROM_QSTR(MP_QSTR_Timer3), MP_ROM_INT(Timer3) }, -}; -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 diff --git a/ports/quectel/machine_uart.c b/ports/quectel/machine_uart.c deleted file mode 100644 index a52d7d1e3db69..0000000000000 --- a/ports/quectel/machine_uart.c +++ /dev/null @@ -1,492 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020-2021 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 - -#include "runtime.h" -#include "stream.h" -#include "mperrno.h" -#include "mphalport.h" - -#if MICROPY_QPY_MACHINE_UART - -#include "helios_uart.h" -#include "helios_pin.h" -#include "helios_debug.h" -#include "callbackdeal.h" - -typedef struct _machine_uart_obj_t { - mp_obj_base_t base; - unsigned int uart_num; - Helios_UARTConfig config; -} machine_uart_obj_t; - -static c_callback_t *callback_cur[HELIOS_UARTMAX] = {0}; - -static machine_uart_obj_t *uart_self_obj[HELIOS_UARTMAX] = {0}; - - -const mp_obj_type_t machine_uart_type; -static const char *_parity_name[] = {"None", "1", "0"}; - -/******************************************************************************/ -// MicroPython bindings for UART - -static void machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=%s, stop=%u, flow=%u", - self->uart_num, self->config.baudrate, self->config.data_bit, _parity_name[self->config.parity_bit], - self->config.stop_bit, self->config.flow_ctrl); - mp_printf(print, ")"); -} - -static void machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_flow}; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_bits, MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_parity, MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_stop, MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_flow, 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); - - // get baudrate bits - switch (args[ARG_baudrate].u_int) { - case HELIOS_UART_BAUD_300: - case HELIOS_UART_BAUD_600: - case HELIOS_UART_BAUD_1200: - case HELIOS_UART_BAUD_2400: - case HELIOS_UART_BAUD_3600: - case HELIOS_UART_BAUD_4800: - case HELIOS_UART_BAUD_7200: - case HELIOS_UART_BAUD_9600: - case HELIOS_UART_BAUD_14400: - case HELIOS_UART_BAUD_19200: - case HELIOS_UART_BAUD_28800: - case HELIOS_UART_BAUD_33600: - case HELIOS_UART_BAUD_38400: - case HELIOS_UART_BAUD_57600: - case HELIOS_UART_BAUD_115200: - case HELIOS_UART_BAUD_230400: - case HELIOS_UART_BAUD_460800: - case HELIOS_UART_BAUD_921600: - case HELIOS_UART_BAUD_1000000: - case HELIOS_UART_BAUD_1842000: - case HELIOS_UART_BAUD_3686400: - case HELIOS_UART_BAUD_4468750: - self->config.baudrate = args[ARG_baudrate].u_int; - break; - default: - mp_raise_ValueError(MP_ERROR_TEXT("invalid baudrate")); - break; - } - - // get data bits -#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_Unisoc_8910_R06) - switch (args[ARG_bits].u_int) { - case 8: - self->config.data_bit = HELIOS_UART_DATABIT_8; - break; - default: - mp_raise_ValueError(MP_ERROR_TEXT("invalid data bits, Unisoc platform only support 8 data bit.")); - break; - } -#else - switch (args[ARG_bits].u_int) { - case 5: - self->config.data_bit = HELIOS_UART_DATABIT_5; - break; - case 6: - self->config.data_bit = HELIOS_UART_DATABIT_6; - break; - case 7: - self->config.data_bit = HELIOS_UART_DATABIT_7; - break; - case 8: - self->config.data_bit = HELIOS_UART_DATABIT_8; - break; - default: - mp_raise_ValueError(MP_ERROR_TEXT("invalid data bits")); - break; - } -#endif - // get parity bits - switch (args[ARG_parity].u_int) { - case 0: - self->config.parity_bit = HELIOS_UART_PARITY_NONE; - break; - case 1: - self->config.parity_bit = HELIOS_UART_PARITY_EVEN; - break; - case 2: - self->config.parity_bit = HELIOS_UART_PARITY_ODD; - break; - #if defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1602) - case 3: - self->config.parity_bit = HELIOS_UART_PARITY_MARK; - break; - case 4: - self->config.parity_bit = HELIOS_UART_PARITY_SPACE; - break; - #endif - default: - mp_raise_ValueError(MP_ERROR_TEXT("invalid parity bits")); - break; - } - - // get stop bits - switch (args[ARG_stop].u_int) { - case 1: - self->config.stop_bit = HELIOS_UART_STOP_1; - break; - case 2: - self->config.stop_bit = HELIOS_UART_STOP_2; - break; - default: - mp_raise_ValueError(MP_ERROR_TEXT("invalid stop bits")); - break; - } - - // get flow bits - switch (args[ARG_flow].u_int) { - case 0: - self->config.flow_ctrl = HELIOS_UART_FC_NONE; - break; - case 1: - self->config.flow_ctrl = HELIOS_UART_FC_HW; - break; - default: - mp_raise_ValueError(MP_ERROR_TEXT("invalid flow bits")); - break; - } - Helios_UARTInitStruct uart_para = {0}; - Helios_UARTConfig uart_config = {0}; - uart_para.uart_config = &uart_config; - - memcpy((void*)&uart_config,(void*)&self->config, sizeof(Helios_UARTConfig)); - if(self->uart_num == QPY_REPL_UART) { - mp_hal_port_open(0); - } -//Helios_UART_Init has created a timer in kernal and Helios_UART_Deinit will delete this timer of Sony. -//So if we deint uart first, moudle will dump. -#ifndef PLAT_SONY_ALT1350 - Helios_UART_Deinit((Helios_UARTNum) self->uart_num); -#endif - - if(Helios_UART_Init((Helios_UARTNum) self->uart_num, &uart_para) != 0) { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("UART(%d) init fail"), self->uart_num); - } -} - -static mp_obj_t machine_uart_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, MP_OBJ_FUN_ARGS_MAX, true); - - // get uart id - mp_int_t uart_num = mp_obj_get_int(args[0]); - if (uart_num < HELIOS_UART0 || uart_num > HELIOS_UARTMAX) { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("UART(%d) does not exist"), uart_num); - } - - // create instance - if (uart_self_obj[uart_num] == NULL) - { - uart_self_obj[uart_num] = mp_obj_malloc_with_finaliser(machine_uart_obj_t, &machine_uart_type); - } - machine_uart_obj_t *self = uart_self_obj[uart_num]; - - self->base.type = &machine_uart_type; - self->uart_num = uart_num; - self->config.baudrate = HELIOS_UART_BAUD_115200; - self->config.data_bit = HELIOS_UART_DATABIT_8; - self->config.stop_bit = HELIOS_UART_STOP_1; - self->config.parity_bit = HELIOS_UART_PARITY_NONE; - self->config.flow_ctrl = HELIOS_UART_FC_NONE; - - mp_map_t kw_args; - mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); - machine_uart_init_helper(self, n_args - 1, args + 1, &kw_args); - - return MP_OBJ_FROM_PTR(self); -} - -static mp_obj_t machine_uart_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { - machine_uart_init_helper(args[0], n_args - 1, args + 1, kw_args); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_KW(machine_uart_init_obj, 1, machine_uart_init); - -static mp_obj_t machine_uart_deinit(mp_obj_t self_in) { - machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - - int ret = Helios_UART_Deinit((Helios_UARTNum) self->uart_num); - if(self->uart_num == QPY_REPL_UART) { - mp_hal_port_open(1); - } - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_deinit_obj, machine_uart_deinit); - - -static mp_obj_t machine_uart_any(mp_obj_t self_in) { - machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - size_t rxbufsize; - rxbufsize = Helios_UART_Any((Helios_UARTNum) self->uart_num); - return MP_OBJ_NEW_SMALL_INT(rxbufsize); -} -static MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_any_obj, machine_uart_any); - -#if defined (PLAT_ASR) || defined (PLAT_Unisoc) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_Unisoc_8850) || defined(PLAT_Unisoc_8850_R02) \ - || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_EIGEN) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_ASR_1602) || defined(PLAT_aic8800m40) || defined(PLAT_Unisoc_8910_R06) -enum{ARG_self, ARG_gipo_n, ARG_direc, ARG_block}; -static mp_obj_t machine_uart_485_control(mp_uint_t n_args, const mp_obj_t *args){ - int ret = -1; - if(n_args < 3) - { - mp_raise_ValueError(MP_ERROR_TEXT("invalid parameter")); - } - machine_uart_obj_t *self = MP_OBJ_TO_PTR(args[ARG_self]); - size_t gpio = mp_obj_get_int(args[ARG_gipo_n]); - Helios_UART_Direc dire = (Helios_UART_Direc)mp_obj_get_int(args[ARG_direc]); - ret = Helios_UART_SetCtl_485(self->uart_num,gpio,dire); -#if defined(PLAT_Unisoc_8850) - int set = 0; - if(n_args >= 4) - { - set = mp_obj_get_int(args[ARG_block]); - } - Helios_UART_SetBlockMode_485((char)set); -#endif - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_uart_485_control_obj, 3, 4, (mp_obj_t)machine_uart_485_control); - -#endif - -void helios_uart_callback_to_python(uint64_t ind_type, Helios_UARTNum port, uint64_t size) -{ - if(callback_cur[port] == NULL) { - return; - } - st_CallBack_Uart *Uart_t = malloc(sizeof(st_CallBack_Uart)); - if(NULL != Uart_t) - { - Uart_t->ind_type = ind_type; - Uart_t->port = port; - Uart_t->size = size; - Uart_t->callback = *callback_cur[port]; - qpy_send_msg_to_callback_deal_thread(CALLBACK_TYPE_ID_UART, Uart_t); - } -} - - - -static mp_obj_t helios_uart_set_callback(mp_obj_t self_in, mp_obj_t callback) -{ - machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - static c_callback_t cb[sizeof(callback_cur) / sizeof(callback_cur[0])] = {0}; - memset(&cb[self->uart_num], 0, sizeof(c_callback_t)); - cb[self->uart_num].arg = mp_obj_new_tuple(3, NULL); - callback_cur[self->uart_num] = &cb[self->uart_num]; - mp_sched_schedule_callback_register(callback_cur[self->uart_num], callback); - - int ret = Helios_UART_SetCallback((Helios_UARTNum) self->uart_num, (Helios_UARTCallback) helios_uart_callback_to_python); - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_2(machine_uart_set_callback_obj, helios_uart_set_callback); - -static mp_obj_t helios_uart_deinit(mp_obj_t self_in) -{ - int ret = 0; - - machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - - uart_self_obj[self->uart_num] = NULL; - callback_cur[self->uart_num] = NULL; - ret = Helios_UART_Deinit((Helios_UARTNum) self->uart_num); - - if(self->uart_num == QPY_REPL_UART) { - mp_hal_port_open(1); - } - - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_1(helios_uart_deinit_obj, helios_uart_deinit); - -#if defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) -static mp_obj_t machine_uart_rx_disable(mp_obj_t self_in,mp_obj_t set) -{ - int ret = -1; - machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - size_t set_value = mp_obj_get_int(set); - if(set_value > 1) - { - mp_raise_ValueError(MP_ERROR_TEXT("setting_value must be 0 or 1")); - } - ret = Helios_Uart_Disable_Rx(self->uart_num,set_value); - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_2(machine_uart_rx_disable_obj, machine_uart_rx_disable); -#endif - -static const mp_rom_map_elem_t machine_uart_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&helios_uart_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_uart_init_obj) }, - { MP_ROM_QSTR(MP_QSTR_close), 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_read), MP_ROM_PTR(&mp_stream_read_obj) }, - { MP_ROM_QSTR(MP_QSTR_set_callback), MP_ROM_PTR(&machine_uart_set_callback_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_writeOnce), MP_ROM_PTR(&mp_stream_write1_obj) }, - { MP_ROM_QSTR(MP_QSTR_readOnce), MP_ROM_PTR(&mp_stream_read1_obj) }, - -#if defined(PLAT_RDA) - { MP_ROM_QSTR(MP_QSTR_UART1), MP_ROM_INT(HELIOS_UART1) }, -#endif -#if defined (PLAT_ASR) || defined (PLAT_Unisoc) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_Unisoc_8850) || defined(PLAT_Unisoc_8850_R02) \ - || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_EIGEN) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_ASR_1602) || defined(PLAT_aic8800m40) || defined(PLAT_Unisoc_8910_R06) - { MP_ROM_QSTR(MP_QSTR_control_485), MP_ROM_PTR(&machine_uart_485_control_obj) }, - PLAT_GPIO_DEF(PLAT_GPIO_NUM), -#endif -#if defined (PLAT_ASR) || defined(PLAT_Qualcomm) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_EIGEN) \ - || defined(PLAT_ASR_1602) || defined(PLAT_ECR6600) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(BOARD_BC32RA) || defined(BOARD_BC92RB) \ - || defined(PLAT_EIGEN_718) || defined(PLAT_aic8800m40) - { MP_ROM_QSTR(MP_QSTR_UART0), MP_ROM_INT(HELIOS_UART0) }, -#endif - -#if !defined(PLAT_RDA) -#if !defined(PLAT_ECR6600) - { MP_ROM_QSTR(MP_QSTR_UART1), MP_ROM_INT(HELIOS_UART1) }, -#endif - { MP_ROM_QSTR(MP_QSTR_UART2), MP_ROM_INT(HELIOS_UART2) }, -#if !defined(PLAT_ECR6600) - { MP_ROM_QSTR(MP_QSTR_UART3), MP_ROM_INT(HELIOS_UART3) }, -#endif -#endif - -#if defined(PLAT_Qualcomm) \ - || defined (PLAT_Unisoc) \ - || defined(PLAT_Unisoc_8910_R05) \ - || defined(PLAT_Unisoc_8910_R06) \ - || defined(BOARD_EC600GCN_LD) \ - || defined(BOARD_EC600GCN_LA) \ - || defined(BOARD_EC600GCN_LA_CDD) \ - || defined(BOARD_EC600GCN_LD_YM) \ - || defined(BOARD_EG700GCN_LC) \ - || defined (PLAT_ASR) \ - || MICROPY_QPY_UART4 - { MP_ROM_QSTR(MP_QSTR_UART4), MP_ROM_INT(HELIOS_UART4) }, -#endif - -#if defined(PLAT_Unisoc_8850) || defined(PLAT_Unisoc_8850_R02) || MICROPY_QPY_USB_DOUBLE_CDC - { MP_ROM_QSTR(MP_QSTR_UART5), MP_ROM_INT(HELIOS_UART5) }, -#endif - -#if defined(PLAT_Unisoc_8850) || defined(PLAT_Unisoc_8850_R02) - { MP_ROM_QSTR(MP_QSTR_UART6), MP_ROM_INT(HELIOS_UART6) }, -#endif - -#if defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) - { MP_ROM_QSTR(MP_QSTR_rx_auto_disable), MP_ROM_PTR(&machine_uart_rx_disable_obj) }, -#endif - { MP_ROM_QSTR(MP_QSTR_REPL_UART), MP_ROM_INT(QPY_REPL_UART) }, -}; - -static MP_DEFINE_CONST_DICT(machine_uart_locals_dict, machine_uart_locals_dict_table); - -static mp_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) { - machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - - // make sure we want at least 1 char - if (size == 0) { - return 0; - } - - int bytes_read = Helios_UART_Read((Helios_UARTNum) self->uart_num, buf_in, size); - if (bytes_read < 0) { - *errcode = MP_EAGAIN; - return MP_STREAM_ERROR; - } - - return bytes_read; -} - -static mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) { - machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - int bytes_written = Helios_UART_Write((Helios_UARTNum) self->uart_num, (void*)buf_in, size); - if (bytes_written < 0) { - *errcode = MP_EAGAIN; - return MP_STREAM_ERROR; - } - - // return number of bytes written - return bytes_written; -} - -static mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { - //machine_uart_obj_t *self = self_in; - mp_uint_t ret; - if (request == MP_STREAM_POLL) { - mp_uint_t flags = (mp_uint_t)arg; - ret = 0; - size_t rxbufsize = 1; - if ((flags & MP_STREAM_POLL_RD) && rxbufsize > 0) { - ret |= MP_STREAM_POLL_RD; - } - if ((flags & MP_STREAM_POLL_WR) && 1) { // FIXME: uart_tx_any_room(self->uart_num) - ret |= MP_STREAM_POLL_WR; - } - } else { - *errcode = MP_EINVAL; - ret = MP_STREAM_ERROR; - } - return ret; -} - -static const mp_stream_p_t uart_stream_p = { - .read = machine_uart_read, - .write = machine_uart_write, - .ioctl = machine_uart_ioctl, - .is_text = false, -}; - -MP_DEFINE_CONST_OBJ_TYPE( - machine_uart_type, - MP_QSTR_UART, - MP_TYPE_FLAG_NONE, - make_new, machine_uart_make_new, - print, machine_uart_print, - protocol, &uart_stream_p, - locals_dict, &machine_uart_locals_dict - ); - -#endif diff --git a/ports/quectel/machine_wdt.c b/ports/quectel/machine_wdt.c deleted file mode 100644 index 7ef3b6eda2146..0000000000000 --- a/ports/quectel/machine_wdt.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020-2021 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 "modmachine.h" -#include "mphalport.h" -#include "py/obj.h" -#include "py/mphal.h" -#include "py/smallint.h" -#include "utime_mphal.h" - -#include "helios_wdt.h" -typedef struct _machine_wdt_init_t -{ - mp_obj_base_t base; -}machine_wdt_init_t; -const mp_obj_type_t machine_wdt_type; - -typedef struct _machine_wdt_obj_t -{ - int status; // Y/N - int period; -}machine_wdt_obj_t; - -static machine_wdt_init_t machine_wdt_obj = {0}; - -static mp_obj_t machine_wdt_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, true); - - machine_wdt_init_t *self = &machine_wdt_obj; - machine_wdt_obj_t info = {0}; - self->base.type = &machine_wdt_type; - if (n_args > 0) - { - info.period = mp_obj_get_int(args[0]); - --n_args; - ++args; - } - Helios_WDT_Deinit(); - if(0 != Helios_WDT_Init((uint64_t) info.period)) { - return mp_const_false; - } - return MP_OBJ_FROM_PTR(self); -} - - -static mp_obj_t machine_wdt_feed(const mp_obj_t arg0) -{ - Helios_WDT_Feed(); - return mp_obj_new_int(0); -} -static MP_DEFINE_CONST_FUN_OBJ_1(machine_wdt_feed_obj, machine_wdt_feed); - - -static mp_obj_t machine_wdt_stop(const mp_obj_t arg0) -{ - Helios_WDT_Deinit(); - return mp_obj_new_int(0); -} -static MP_DEFINE_CONST_FUN_OBJ_1(machine_wdt_stop_obj, machine_wdt_stop); - - -static const mp_rom_map_elem_t machine_wdt_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_feed), MP_ROM_PTR(&machine_wdt_feed_obj) }, - { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&machine_wdt_stop_obj) }, -}; -static MP_DEFINE_CONST_DICT(machine_wdt_locals_dict, machine_wdt_locals_dict_table); - -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/quectel/main.c b/ports/quectel/main.c index 71b6a2ae8969f..23fbe9275e25c 100644 --- a/ports/quectel/main.c +++ b/ports/quectel/main.c @@ -46,7 +46,6 @@ #include "helios_os.h" #include "helios_debug.h" #include "mphalport.h" -#include "callbackdeal.h" #if MICROPY_KBD_EXCEPTION #include "shared/runtime/interrupt_char.h" #endif @@ -109,14 +108,8 @@ void __assert_fail(const char *__message, static char *stack_top; #if MICROPY_ENABLE_GC -#if defined(PLAT_ECR6600) -static char __attribute__((__section__(".data"))) heap[MICROPY_GC_HEAP_SIZE]; -#elif defined(PLAT_SONY_ALT1350) -static char __attribute__((__section__("gpm1_working_data"))) heap[MICROPY_GC_HEAP_SIZE]; -#else static char heap[MICROPY_GC_HEAP_SIZE]; #endif -#endif extern pyexec_mode_kind_t pyexec_mode_kind; @@ -180,21 +173,7 @@ void quecpython_task(void *arg) readline_init0(); // run boot-up scripts -#if defined(PLAT_RDA) - pyexec_frozen_module("_boot_RDA.py"); -#elif defined(PLAT_Qualcomm) - pyexec_frozen_module("_boot_Qualcomm.py"); -#elif defined(BOARD_EC800ECN_LC_WDF) - pyexec_frozen_module("_boot_WDF.py");//EIGEN WDF CUNSTOMER BOOT WITH SINGEL FILE SYSTEM -#elif defined(PLAT_ECR6600) || defined(PLAT_aic8800m40) - pyexec_frozen_module("_boot_WIFI.py"); -#elif defined(BOARD_EC600GCN_LA_CDD) - pyexec_frozen_module("_boot_dsds.py"); -#elif defined(PLAT_SONY_ALT1350) - pyexec_frozen_module("_boot_SONY.py", false); -#else pyexec_frozen_module("_boot.py", false); -#endif if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL #if MICROPY_PY_KBD_EXCEPTION diff --git a/ports/quectel/misc_adc.c b/ports/quectel/misc_adc.c deleted file mode 100644 index 7f867498ab7f6..0000000000000 --- a/ports/quectel/misc_adc.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020-2021 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 "stdio.h" -#include "stdlib.h" -#include -#include "py/obj.h" -#include "py/runtime.h" -#include "mphalport.h" - -#if MICROPY_QPY_MISC_ADC - -#include "helios_adc.h" - -typedef enum -{ - ADC0 = 0, - ADC1 = 1, - ADC2 = 2, - ADC3 = 3, -}ADCn; - -typedef struct _misc_adc_obj_t { - mp_obj_base_t base; - unsigned int pin; -} misc_adc_obj_t; - -const mp_obj_type_t misc_adc_type; - -static mp_obj_t Helios_adc_init(mp_obj_t self_in) -{ - int ret = Helios_ADC_Init(); - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_1(Helios_adc_init_obj, Helios_adc_init); - -static mp_obj_t Helios_adc_read(mp_obj_t self_in, mp_obj_t adc_channel) -{ - int ret = -1; - int channel = mp_obj_get_int(adc_channel); - if ((channel == 0) || (channel == 1) || (channel == 2) || (channel == 3)) - { - unsigned int chl = channel; - //ret = ql_adc_read(chl, &batvol); - - ret = Helios_ADC_Read((Helios_ADCNum) chl); - return mp_obj_new_int(ret); - } - return mp_obj_new_int(-1); -} -static MP_DEFINE_CONST_FUN_OBJ_2(Helios_adc_read_obj, Helios_adc_read); - -static mp_obj_t Helios_adc_deinit(mp_obj_t self_in) -{ - int ret = Helios_ADC_Deinit(); - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_1(Helios_adc_deinit_obj, Helios_adc_deinit); - - - -static const mp_rom_map_elem_t misc_adc_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&Helios_adc_init_obj) }, - { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&Helios_adc_read_obj) }, - { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&Helios_adc_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR_ADC0), MP_ROM_INT(ADC0) }, -#if !defined(PLAT_Qualcomm) - { MP_ROM_QSTR(MP_QSTR_ADC1), MP_ROM_INT(ADC1) }, -#if !defined(PLAT_Unisoc_8850) && !defined(BOARD_EC600ECN_LC) && !defined(PLAT_SONY_ALT1350) - { MP_ROM_QSTR(MP_QSTR_ADC2), MP_ROM_INT(ADC2) }, - { MP_ROM_QSTR(MP_QSTR_ADC3), MP_ROM_INT(ADC3) }, -#endif -#endif -}; -static MP_DEFINE_CONST_DICT(misc_adc_locals_dict, misc_adc_locals_dict_table); - -static mp_obj_t misc_adc_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, MP_OBJ_FUN_ARGS_MAX, true); - - // create ADC object - misc_adc_obj_t *self = m_new_obj(misc_adc_obj_t); - self->base.type = &misc_adc_type; - return MP_OBJ_FROM_PTR(self); -} - -MP_DEFINE_CONST_OBJ_TYPE( - misc_adc_type, - MP_QSTR_ADC, - MP_TYPE_FLAG_NONE, - make_new, misc_adc_make_new, - locals_dict, &misc_adc_locals_dict - ); -#endif /* MICROPY_QPY_MISC_ADC */ - - diff --git a/ports/quectel/misc_power.c b/ports/quectel/misc_power.c deleted file mode 100644 index 93eafd8fcfc03..0000000000000 --- a/ports/quectel/misc_power.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020-2021 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 "stdlib.h" -#include "mpconfigport.h" -#include "py/obj.h" -#include "py/compile.h" -#include "py/runtime.h" -#include "py/repl.h" -#include "py/mperrno.h" - -#if MICROPY_QPY_MISC_POWER - -#include "modmisc.h" -#include "helios_power.h" - -const mp_obj_type_t misc_power_type; - -static mp_obj_t misc_power_reset() -{ - int ret = 1; - Helios_Power_Reset(ret); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_0(misc_power_reset_obj, misc_power_reset); - - -static mp_obj_t misc_power_down() -{ - int ret = 1; - Helios_Power_Down(ret); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_0(misc_power_down_obj, misc_power_down); - -static mp_obj_t misc_power_get_down_reason() -{ - int ret; - ret = Helios_Power_GetDownReason(); - return mp_obj_new_int(ret); -} - -#if !defined(PLAT_RDA) -static MP_DEFINE_CONST_FUN_OBJ_0(misc_power_get_down_reason_obj, misc_power_get_down_reason); -#endif -static mp_obj_t misc_power_get_up_reason() -{ - int ret = 0; - ret = Helios_Power_GetUpReason(); - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_0(misc_power_get_up_reason_obj, misc_power_get_up_reason); - - -static mp_obj_t misc_power_get_batt() -{ - unsigned int ret; - ret = Helios_Power_GetBatteryVol(); - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_0(misc_power_get_batt_obj, misc_power_get_batt); - -static const mp_rom_map_elem_t misc_power_locals_dict_table[] = { - { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_misc) }, - { MP_ROM_QSTR(MP_QSTR_powerRestart), MP_ROM_PTR(&misc_power_reset_obj) }, - { MP_ROM_QSTR(MP_QSTR_powerDown), MP_ROM_PTR(&misc_power_down_obj) }, - { MP_ROM_QSTR(MP_QSTR_powerOnReason), MP_ROM_PTR(&misc_power_get_up_reason_obj) }, -#if !defined(PLAT_RDA) - { MP_ROM_QSTR(MP_QSTR_powerDownReason), MP_ROM_PTR(&misc_power_get_down_reason_obj) }, -#endif - { MP_ROM_QSTR(MP_QSTR_getVbatt), MP_ROM_PTR(&misc_power_get_batt_obj) }, -}; - -static MP_DEFINE_CONST_DICT(misc_power_locals_dict, misc_power_locals_dict_table); - -MP_DEFINE_CONST_OBJ_TYPE( - misc_power_type, - MP_QSTR_Power, - MP_TYPE_FLAG_NONE, - locals_dict, &misc_power_locals_dict -); -#endif /* MICROPY_QPY_MISC_POWER */ diff --git a/ports/quectel/misc_pwm.c b/ports/quectel/misc_pwm.c deleted file mode 100644 index bf592d1279a73..0000000000000 --- a/ports/quectel/misc_pwm.c +++ /dev/null @@ -1,390 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020-2021 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 "runtime.h" - -#if MICROPY_QPY_MISC_PWM - -#include "helios_pwm.h" -#include "helios_debug.h" - - -#define PWM_LOG(msg, ...) custom_log("pwm", msg, ##__VA_ARGS__) - - - -// Forward dec'l -const mp_obj_type_t misc_pwm_type; -const mp_obj_type_t misc_pwm_v2_type; - -typedef enum -{ - PWM_V1=0, - PWM_V2 -}pwm_type_t; - -typedef struct _misc_pwm_obj_t { - mp_obj_base_t base; - unsigned int pin; - unsigned int cycle_range; - unsigned short high_time; - unsigned short cycle_time; - unsigned char duty; - float frequency; - pwm_type_t type_pwm; -#if defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) - unsigned char pwm_en_sleep; -#endif -} misc_pwm_obj_t; - -typedef enum HELIOS_PWM_CYCLE_RANGE_ENUM -{ - HELIOS_PWM_CYCLE_ABOVE_1US, - HELIOS_PWM_CYCLE_ABOVE_1MS, - HELIOS_PWM_CYCLE_ABOVE_10US, - HELIOS_PWM_CYCLE_ABOVE_BELOW_US, -} HELIOS_PWM_CYCLE_RANGE_E; - -static misc_pwm_obj_t *misc_pwm_obj[PWMMAX] = {NULL}; - -static void misc_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - misc_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "PWM(pin:%u high time:%u cycle_time:%u)", self->pin, self->high_time, self->cycle_time); -} - - -typedef struct { - uint16_t Left_coordinate; - uint16_t Right_coordinata; -}Helios_PWM_range; - - -//helios_pwm[0]:1US -//helios_pwm[1]:1ms -//helios_pwm[2]:10us -//helios_pwm[3]:ns -#if defined(PLAT_ASR) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1602) -const Helios_PWM_range helios_pwm[4] = {{0, 157}, {0, 1023}, {1, 1575}, {0, 1024}}; - -#elif defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_ECR6600) || defined(PLAT_Unisoc_8850_R02) || defined(PLAT_Unisoc_8910_R06) -const Helios_PWM_range helios_pwm[4] = {{0, 10000}, {0, 10}, {1, 10000}, {99, 65535}}; -#elif defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) -#elif defined(PLAT_EIGEN) -#elif defined(PLAT_Qualcomm) -#elif defined(PLAT_SONY_ALT1350) - -#else -#error "Please check whether the platform supports PWM" -#endif - - -#if !defined(PLAT_ASR_1803s) && !defined(PLAT_ASR_1803sc) && !defined(PLAT_EIGEN) && !defined(PLAT_Qualcomm) && !defined(PLAT_SONY_ALT1350) -static int check_pwm_para(uint16_t cycle_range, uint16_t cycle_time, uint16_t hight_time) { - - if(cycle_range > HELIOS_PWM_CYCLE_ABOVE_BELOW_US || - hight_time <= helios_pwm[cycle_range].Left_coordinate || hight_time > helios_pwm[cycle_range].Right_coordinata || - cycle_time <= helios_pwm[cycle_range].Left_coordinate || cycle_time > helios_pwm[cycle_range].Right_coordinata || - hight_time > cycle_time) { - return -1; - } - return 0; -} -#endif -static void misc_pwm_init_helper(misc_pwm_obj_t *self, - size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_cycle_range, ARG_high_time, ARG_cycle_time }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_cycle_range, MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_high_time, MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_cycle_time, MP_ARG_INT, {.u_int = 0} }, -#if defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) - { MP_QSTR_pwm_en_sleep, MP_ARG_INT, {.u_int = 0} }, -#endif - }; - 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); - - //PWM_LOG("cycle_range=%d, high_time=%d, cycle_time=%d\n",args[ARG_cycle_range].u_int, args[ARG_high_time].u_int, args[ARG_cycle_time].u_int); -#if !(defined(PLAT_ASR) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) \ - || defined(PLAT_EIGEN) || defined(PLAT_Qualcomm) || defined(PLAT_ECR6600) || defined(PLAT_ASR_1602) || defined(PLAT_SONY_ALT1350)) - if(-1 == check_pwm_para(args[ARG_cycle_range].u_int, args[ARG_cycle_time].u_int, args[ARG_high_time].u_int)) { - mp_raise_ValueError(MP_ERROR_TEXT("PWM parameter error, please refer to wiki instructions to correct the parameters")); - } -#endif - - self->cycle_range = args[ARG_cycle_range].u_int; - self->high_time = args[ARG_high_time].u_int; - self->cycle_time = args[ARG_cycle_time].u_int; - self->type_pwm = PWM_V1; - PWM_LOG("cycle_range=%d, high_time=%d, cycle_time=%d\n",self->cycle_range, self->high_time, self->cycle_time); - - if(Helios_PWM_Init(self->pin) != 0) { - mp_raise_ValueError(MP_ERROR_TEXT("fail")); - } - -#if defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) - Helios_PWM_En_Sleep(self->pin,args[3].u_int); - PWM_LOG("Helios_PWM_En_Sleep->%d\n",args[3].u_int); -#endif -} - -static mp_obj_t misc_pwm_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, 4, 5, true); - int pin_id = mp_obj_get_int(args[0]); - - PWM_LOG("n_args = %d\n",n_args); - - if ((pin_id < 0) || (pin_id > PWMMAX-1)) - { - mp_raise_ValueError(MP_ERROR_TEXT("invalid PWMn value, must be in {0~3}.")); - } - - // create PWM object from the given pin - if (misc_pwm_obj[pin_id] == NULL) - { - misc_pwm_obj[pin_id] = mp_obj_malloc_with_finaliser(misc_pwm_obj_t, &misc_pwm_type); - } - misc_pwm_obj_t *self = misc_pwm_obj[pin_id]; - self->base.type = &misc_pwm_type; - self->pin = pin_id; - - mp_map_t kw_args; - mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); - misc_pwm_init_helper(self, n_args - 1, args + 1, &kw_args); - - return MP_OBJ_FROM_PTR(self); -} - -static mp_obj_t misc_pwm_init(size_t n_args, - const mp_obj_t *args, mp_map_t *kw_args) { - misc_pwm_init_helper(args[0], n_args - 1, args + 1, kw_args); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_KW(misc_pwm_init_obj, 1, misc_pwm_init); - -//pwm v2 init by pass duty and frequency 20220624 @jimmy -static void misc_pwm_v2_init_helper(misc_pwm_obj_t *self, - size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) -{ - enum {ARG_frequency,ARG_duty}; - static const mp_arg_t allowed_args[] = - { - { MP_QSTR_frequency, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_duty, MP_ARG_INT, {.u_int = 0} }, -#if defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) - { MP_QSTR_pwm_en_sleep, MP_ARG_INT, {.u_int = 0} }, -#endif - }; - - 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(mp_obj_is_float(args[ARG_frequency].u_obj) == 0) - { - mp_raise_TypeError(MP_ERROR_TEXT("frequency type isn't float")); - } - if(args[ARG_duty].u_int > 100) - { - mp_raise_ValueError(MP_ERROR_TEXT("PWM parameter error,range duty should be 0~100")); - } - self->duty = args[ARG_duty].u_int; - self->frequency = mp_obj_float_get(args[ARG_frequency].u_obj); - self->type_pwm = PWM_V2; - - if(Helios_PWM_Init(self->pin) != 0) { - mp_raise_ValueError(MP_ERROR_TEXT("fail")); - } -#if defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) - Helios_PWM_En_Sleep(self->pin,args[2].u_int); - PWM_LOG("Helios_PWM_En_Sleep->%d\n",args[2].u_int); -#endif - -} -static mp_obj_t misc_pwm_v2_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, 3, 4, true); - int pin_id = mp_obj_get_int(args[0]); - - if ((pin_id < 0) || (pin_id > PWMMAX-1)) - { - mp_raise_ValueError(MP_ERROR_TEXT("invalid PWMn value, must be in {0~3}.")); - } - - // create PWM object from the given pin - if (misc_pwm_obj[pin_id] == NULL) - { - misc_pwm_obj[pin_id] = mp_obj_malloc_with_finaliser(misc_pwm_obj_t, &misc_pwm_type); - } - misc_pwm_obj_t *self = misc_pwm_obj[pin_id]; - self->base.type = &misc_pwm_v2_type; - self->pin = pin_id; - - mp_map_t kw_args; - mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); - misc_pwm_v2_init_helper(self, n_args - 1, args + 1, &kw_args); - - return MP_OBJ_FROM_PTR(self); -} - -static mp_obj_t misc_pwm_enable(size_t n_args, const mp_obj_t *args) -{ - misc_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]); - if(self->type_pwm == PWM_V1) - { - PWM_LOG("cycle_range=%d, high_time=%d, cycle_time=%d\n",self->cycle_range, self->high_time, self->cycle_time); - double frequency = 0; - float duty = 0; - if(n_args == 4) - { -#if !(defined(PLAT_ASR) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) \ - || defined(PLAT_EIGEN) || defined(PLAT_Qualcomm) || defined(PLAT_ECR6600) || defined(PLAT_ASR_1602) || defined(PLAT_SONY_ALT1350)) - if(-1 == check_pwm_para(mp_obj_get_int(args[1]), mp_obj_get_int(args[3]), mp_obj_get_int(args[2]))) - { - mp_raise_ValueError(MP_ERROR_TEXT("PWM parameter error, please refer to wiki instructions to correct the parameters")); - } -#endif - self->cycle_range = mp_obj_get_int(args[1]); - self->cycle_time = mp_obj_get_int(args[3]); - self->high_time = mp_obj_get_int(args[2]); - } - - if(self->cycle_range == HELIOS_PWM_CYCLE_ABOVE_1US || self->cycle_range == HELIOS_PWM_CYCLE_ABOVE_10US) - { - frequency = 1000000 /(double)self->cycle_time; - } - else if (self->cycle_range == HELIOS_PWM_CYCLE_ABOVE_1MS) - { - frequency = 1000 /(double)self->cycle_time; - } - else if(self->cycle_range == HELIOS_PWM_CYCLE_ABOVE_BELOW_US) - { - frequency = 1000000000 /(double)self->cycle_time; - } - duty = (float)self->high_time / (float)self->cycle_time; - - PWM_LOG("misc_pwm_enable = %lf %f\n",frequency, duty); - - int ret = Helios_PWM_Start(self->pin, frequency, duty); - - return mp_obj_new_int(ret); - } - else - { - if(n_args == 3) - { - if((mp_obj_get_int(args[2]) < 0) || (mp_obj_get_int(args[2]) > 100)) - { - mp_raise_ValueError(MP_ERROR_TEXT("PWM parameter error,range duty should be 0~100")); - } - if(mp_obj_is_float(args[1]) == 0) - { - mp_raise_TypeError(MP_ERROR_TEXT("frequency type isn't float")); - } - self->frequency = mp_obj_float_get(args[1]); - self->duty = mp_obj_get_int(args[2]); - } - PWM_LOG("duty=%d, frequency=%f\n",self->duty, self->frequency); - - int ret = Helios_PWM_Start(self->pin, self->frequency, (self->duty*1.0)/100); - - return mp_obj_new_int(ret); - } -} - -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(misc_pwm_enable_obj, 1, 4, misc_pwm_enable); - -static mp_obj_t misc_pwm_disable(mp_obj_t self_in) -{ - misc_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in); - - int ret = Helios_PWM_Stop(self->pin); - if (ret != 0) - { - ret = -1; - } - - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_1(misc_pwm_disable_obj, misc_pwm_disable); - -static mp_obj_t misc_pwm_deinit(mp_obj_t self_in) -{ - misc_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in); - - misc_pwm_obj[self->pin] = NULL; - - int ret = Helios_PWM_Deinit((Helios_PwnNum)self->pin); - if (ret != 0) - { - PWM_LOG("pwm%d deinit failed.\r\n", self->pin); - } - - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_1(misc_pwm_deinit_obj, misc_pwm_deinit); - -static const mp_rom_map_elem_t misc_pwm_locals_dict_table[] = { - // { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&misc_pwm_init_obj) }, - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&misc_pwm_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&misc_pwm_enable_obj) }, - { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&misc_pwm_disable_obj) }, - { MP_ROM_QSTR(MP_QSTR_ABOVE_1US), MP_ROM_INT(HELIOS_PWM_CYCLE_ABOVE_1US) }, - { MP_ROM_QSTR(MP_QSTR_ABOVE_MS), MP_ROM_INT(HELIOS_PWM_CYCLE_ABOVE_1MS) }, - { MP_ROM_QSTR(MP_QSTR_ABOVE_10US), MP_ROM_INT(HELIOS_PWM_CYCLE_ABOVE_10US) }, - { MP_ROM_QSTR(MP_QSTR_ABOVE_BELOW_US), MP_ROM_INT(HELIOS_PWM_CYCLE_ABOVE_BELOW_US) }, - { MP_ROM_QSTR(MP_QSTR_PWM0), MP_ROM_INT(PWM0) }, - #if !defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_Unisoc_8910_R06) || defined(PLAT_SONY_ALT1350) - PLAT_PWM_DEF(PLAT_PWM_NUMMAX), - #endif -}; - -static MP_DEFINE_CONST_DICT(misc_pwm_locals_dict, - misc_pwm_locals_dict_table); - - -MP_DEFINE_CONST_OBJ_TYPE( - misc_pwm_type, - MP_QSTR_PWM, - MP_TYPE_FLAG_NONE, - make_new, misc_pwm_make_new, - locals_dict, &misc_pwm_locals_dict - ); - -MP_DEFINE_CONST_OBJ_TYPE( - misc_pwm_v2_type, - MP_QSTR_PWM_V2, - MP_TYPE_FLAG_NONE, - make_new, misc_pwm_v2_make_new, - locals_dict, &misc_pwm_locals_dict - ); - -#endif /* MICROPY_QPY_MISC_PWM */ - diff --git a/ports/quectel/misc_usbnet.c b/ports/quectel/misc_usbnet.c deleted file mode 100644 index 24f61cc07b6f1..0000000000000 --- a/ports/quectel/misc_usbnet.c +++ /dev/null @@ -1,213 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020-2021 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 - -#include "mpconfigport.h" -#include "py/obj.h" -#include "py/compile.h" -#include "py/runtime.h" - -#if MICROPY_QPY_MISC_USBNET - -#include "helios_usbnet.h" -#include "helios_debug.h" - -#define HELIOS_MODUSB_LOG(msg, ...) custom_log("modusbnet", msg, ##__VA_ARGS__) - -STATIC mp_obj_t misc_usbnet_set_type(mp_obj_t type_in) -{ - int type = mp_obj_get_int(type_in); - if (type != HELIOS_USBNET_TYPE_ECM && type != HELIOS_USBNET_TYPE_RNDIS) - { - HELIOS_MODUSB_LOG("USBNET type must be Type_ECM or Type_RNDIS."); - return mp_obj_new_int(-1); - } - int ret = Helios_USBNET_SetType(type); - return mp_obj_new_int(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(misc_usbnet_set_type_obj, misc_usbnet_set_type); - -STATIC mp_obj_t misc_usbnet_get_type(void) -{ - Helios_USBNET_Type_e type = 0; - int ret = Helios_USBNET_GetType(&type); - if (ret == 0) - { - ret = type; - } - return mp_obj_new_int(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(misc_usbnet_get_type_obj, misc_usbnet_get_type); - -STATIC mp_obj_t misc_usbnet_get_status(void) -{ - uint8_t status = 0; - int ret = Helios_USBNET_GetStatus(&status); - if (ret == 0) - { - ret = status; - } - return mp_obj_new_int(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(misc_usbnet_get_status_obj, misc_usbnet_get_status); - -STATIC mp_obj_t misc_usbnet_open(void) -{ - int ret = Helios_USBNET_Open(); - return mp_obj_new_int(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(misc_usbnet_open_obj, misc_usbnet_open); - -STATIC mp_obj_t misc_usbnet_close(void) -{ - int ret = Helios_USBNET_Close(); - return mp_obj_new_int(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(misc_usbnet_close_obj, misc_usbnet_close); - -#if defined(PLAT_Unisoc) -STATIC mp_obj_t misc_usbnet_get_nat(size_t n_args, const mp_obj_t *args) -{ - if (n_args == 2) - { - uint8_t sim_id = mp_obj_get_int(args[0]); - uint8_t profile_id = mp_obj_get_int(args[1]); - if (sim_id != 0) - { - HELIOS_MODUSB_LOG("invalid value, now simId only supports 0."); - return mp_obj_new_int(-1); - } - if (profile_id < 1 || profile_id > 8) - { - HELIOS_MODUSB_LOG("invalid value, profileIdx should be in [1,8]."); - return mp_obj_new_int(-1); - } - int nat = Helios_USBNET_GetNat(sim_id, profile_id); - return mp_obj_new_int(nat); - } - return mp_obj_new_int(-1); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(misc_usbnet_get_nat_obj, 2, 2, misc_usbnet_get_nat); - -STATIC mp_obj_t misc_usbnet_set_nat(size_t n_args, const mp_obj_t *args) -{ - if (n_args == 3) - { - uint8_t sim_id = mp_obj_get_int(args[0]); - uint8_t profile_id = mp_obj_get_int(args[1]); - uint8_t nat = mp_obj_get_int(args[2]); - if (sim_id != 0) - { - HELIOS_MODUSB_LOG("invalid value, now simId only supports 0."); - return mp_obj_new_int(-1); - } - if (profile_id < 1 || profile_id > 8) - { - HELIOS_MODUSB_LOG("invalid value, profileIdx should be in [1,8]."); - return mp_obj_new_int(-1); - } - if (nat != 0 && nat != 1) - { - HELIOS_MODUSB_LOG("invalid value, Nat should be in [0,1]."); - return mp_obj_new_int(-1); - } - int ret = Helios_USBNET_SetNat(sim_id, profile_id, nat); - return mp_obj_new_int(ret); - } - return mp_obj_new_int(-1); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(misc_usbnet_set_nat_obj, 3, 3, misc_usbnet_set_nat); -#endif - -#if defined(PLAT_Unisoc_8850) -STATIC mp_obj_t misc_usbnet_set_MAC(mp_obj_t macinfo) -{ - mp_buffer_info_t m_macinfo; - unsigned char mac[6]; - mp_get_buffer_raise(macinfo, &m_macinfo, MP_BUFFER_READ); - if( m_macinfo.len != 6 ) { - HELIOS_MODUSB_LOG("mac length error"); - return mp_obj_new_int(-1); - } - memcpy(mac, m_macinfo.buf, 6); - - int ret = Helios_USBNET_SetMAC(mac); - - return mp_obj_new_int(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(misc_usbnet_set_MAC_obj, misc_usbnet_set_MAC); - -STATIC mp_obj_t misc_usbnet_set_product(mp_obj_t macinfo) -{ - mp_buffer_info_t m_product; - char product[32]; - mp_get_buffer_raise(macinfo, &m_product, MP_BUFFER_READ); - if( m_product.len > 16 ) { - HELIOS_MODUSB_LOG("product length error"); - return mp_obj_new_int(-1); - } - memset(product, 0x00, sizeof(product)); - strncpy(product, m_product.buf, m_product.len); - - int ret = Helios_USBNET_SetProduct(product); - - return mp_obj_new_int(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(misc_usbnet_set_product_obj, misc_usbnet_set_product); - -#endif - -STATIC const mp_rom_map_elem_t misc_usbnet_locals_dict_table[] = { - {MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_USBNET)}, - {MP_ROM_QSTR(MP_QSTR_set_worktype), MP_ROM_PTR(&misc_usbnet_set_type_obj)}, - {MP_ROM_QSTR(MP_QSTR_get_worktype), MP_ROM_PTR(&misc_usbnet_get_type_obj)}, - {MP_ROM_QSTR(MP_QSTR_get_status), MP_ROM_PTR(&misc_usbnet_get_status_obj)}, - {MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&misc_usbnet_open_obj)}, - {MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&misc_usbnet_close_obj)}, - {MP_ROM_QSTR(MP_QSTR_Type_ECM), MP_ROM_INT(HELIOS_USBNET_TYPE_ECM)}, - {MP_ROM_QSTR(MP_QSTR_Type_RNDIS), MP_ROM_INT(HELIOS_USBNET_TYPE_RNDIS)}, -#if defined(PLAT_Unisoc) - {MP_ROM_QSTR(MP_QSTR_getNat), MP_ROM_PTR(&misc_usbnet_get_nat_obj)}, - {MP_ROM_QSTR(MP_QSTR_setNat), MP_ROM_PTR(&misc_usbnet_set_nat_obj)}, -#endif -#if defined(PLAT_Unisoc_8850) - {MP_ROM_QSTR(MP_QSTR_setMAC), MP_ROM_PTR(&misc_usbnet_set_MAC_obj)}, - {MP_ROM_QSTR(MP_QSTR_setProduct), MP_ROM_PTR(&misc_usbnet_set_product_obj)}, -#endif -}; - -STATIC MP_DEFINE_CONST_DICT(misc_usbnet_locals_dict, misc_usbnet_locals_dict_table); - -const mp_obj_module_t misc_usbnet_module = { - .base = {&mp_type_module}, - .globals = (mp_obj_dict_t *)&misc_usbnet_locals_dict, -}; - -#endif /* MICROPY_QPY_MISC_USBNET */ diff --git a/ports/quectel/moddatacall.c b/ports/quectel/moddatacall.c deleted file mode 100644 index 8d264f170469c..0000000000000 --- a/ports/quectel/moddatacall.c +++ /dev/null @@ -1,833 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020-2021 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 "nlr.h" -#include "objlist.h" -#include "objstr.h" -#include "runtime.h" -#include "mperrno.h" - -#if MICROPY_QPY_MODULE_DATACALL - -#include "helios_debug.h" -#include "helios_datacall.h" -#include "callbackdeal.h" - -#if MICROPY_QPY_MODULE_WANINFO -#include "netif.h" -#include "ip6_addr.h" -#endif - -#define MOD_DATACALL_LOG(msg, ...) custom_log(DataCall, msg, ##__VA_ARGS__) - -extern int _get_current_simid(void); - -static mp_obj_t qpy_datacall_set_pdp_context(size_t n_args, const mp_obj_t *args) -{ - int ret = 0; - int profile_id = mp_obj_get_int(args[0]); - int ip_type = mp_obj_get_int(args[1]); - int auth_type = mp_obj_get_int(args[5]); - - mp_buffer_info_t apninfo = {0}; - mp_buffer_info_t usrinfo = {0}; - mp_buffer_info_t pwdinfo = {0}; - mp_get_buffer_raise(args[2], &apninfo, MP_BUFFER_READ); - mp_get_buffer_raise(args[3], &usrinfo, MP_BUFFER_READ); - mp_get_buffer_raise(args[4], &pwdinfo, MP_BUFFER_READ); - - int min_profile_id = (int)Helios_DataCall_GetProfileIdxMin(); - int max_profile_id = (int)Helios_DataCall_GetProfileIdxMax(); - - if ((profile_id < min_profile_id) || (profile_id > max_profile_id)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, profileID should be in [%d,%d]."), min_profile_id, max_profile_id); - } - if ((ip_type < 0) || (ip_type > HELIOS_PDP_TYPE_NUM - 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, ipType should be in [0~%d]."), HELIOS_PDP_TYPE_NUM - 1); - } - if ((auth_type < 0) || (auth_type > HELIOS_AUTH_TYPE_NUM - 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, authType should be in [0~%d]."), HELIOS_AUTH_TYPE_NUM - 1); - } - if (apninfo.len > HELIOS_APN_LEN_MAX) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, the length of apn should be no more than [%d] bytes."), HELIOS_APN_LEN_MAX); - } - if (usrinfo.len > HELIOS_USR_LEN_MAX) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, the length of username should be no more than [%d] bytes."), HELIOS_USR_LEN_MAX); - } - if (pwdinfo.len > HELIOS_PWD_LEN_MAX) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, the length of password should be no more than [%d] bytes."), HELIOS_PWD_LEN_MAX); - } - if (usrinfo.len == 0 && pwdinfo.len == 0 && auth_type != 0) { - auth_type = 0; - } - - int cur_simid = _get_current_simid(); - if (n_args ==7) { - cur_simid = mp_obj_get_int(args[6]); - } - if ((cur_simid != 0) && (cur_simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); - } - - Helios_DataCallStartStruct pdp_context = {0}; - pdp_context.ip_type = ip_type; - pdp_context.auth = auth_type; - memcpy((void *)pdp_context.apn, apninfo.buf, apninfo.len); - memcpy((void *)pdp_context.user, usrinfo.buf, usrinfo.len); - memcpy((void *)pdp_context.pwd, pwdinfo.buf, pwdinfo.len); - MP_THREAD_GIL_EXIT(); - #if MICROPY_QPY_MODULE_DSDS - ret = Helios_DataCall_SetPDPContext(cur_simid,profile_id, &pdp_context); - #else - ret = Helios_DataCall_SetPDPContext(profile_id, &pdp_context); - #endif - MP_THREAD_GIL_ENTER(); - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_datacall_set_pdp_context_obj, 6, 7, qpy_datacall_set_pdp_context); - - -static mp_obj_t qpy_datacall_get_pdp_context(size_t n_args, const mp_obj_t *args) -{ - int ret = 0; - int profile_id = mp_obj_get_int(args[0]); - Helios_DataCallStartStruct pdp_context = {0}; - - int min_profile_id = (int)Helios_DataCall_GetProfileIdxMin(); - int max_profile_id = (int)Helios_DataCall_GetProfileIdxMax(); - - if ((profile_id < min_profile_id) || (profile_id > max_profile_id)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, profileID should be in [%d,%d]."), min_profile_id, max_profile_id); - } - int cur_simid = _get_current_simid(); - if (n_args ==2) { - cur_simid = mp_obj_get_int(args[1]); - } - if ((cur_simid != 0) && (cur_simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); - } - MP_THREAD_GIL_EXIT(); - #if MICROPY_QPY_MODULE_DSDS - ret = Helios_DataCall_GetPDPContext(cur_simid,profile_id, &pdp_context); - #else - ret = Helios_DataCall_GetPDPContext(profile_id, &pdp_context); - #endif - MP_THREAD_GIL_ENTER(); - if (ret == 0) - { - mp_obj_t pdp_ctx[5] = - { - mp_obj_new_int(pdp_context.ip_type), - mp_obj_new_str(pdp_context.apn, strlen(pdp_context.apn)), - mp_obj_new_str(pdp_context.user, strlen(pdp_context.user)), - mp_obj_new_str(pdp_context.pwd, strlen(pdp_context.pwd)), - mp_obj_new_int(pdp_context.auth) - }; - return mp_obj_new_tuple(5, pdp_ctx); - } - - return mp_obj_new_int(-1); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_datacall_get_pdp_context_obj, 1, 2, qpy_datacall_get_pdp_context); - -/*=============================================================================*/ -/* FUNCTION: qpy_datacall_start */ -/*=============================================================================*/ -/*!@brief : set APN and datacall. - * @profile_idx [in] profile_idx, 1~HELIOS_PROFILE_IDX_MAX - * @ip_type [in] 0-IPV4, 1-IPV6, 2-IPV4 and IPV6 - * @apn_name [in] anp name - * @usr_name [in] user name - * @password [in] password - * @auth_type [in] auth_type, 0-None, 1-PAP, 2-CHAP - * @return : - * - 0--successful - * - -1--error - */ -/*=============================================================================*/ -static mp_obj_t qpy_datacall_start(size_t n_args, const mp_obj_t *args) -{ - int ret = 0; - int profile_id = mp_obj_get_int(args[0]); - int ip_type = mp_obj_get_int(args[1]); - int auth_type = mp_obj_get_int(args[5]); - - mp_buffer_info_t apninfo = {0}; - mp_buffer_info_t usrinfo = {0}; - mp_buffer_info_t pwdinfo = {0}; - mp_get_buffer_raise(args[2], &apninfo, MP_BUFFER_READ); - mp_get_buffer_raise(args[3], &usrinfo, MP_BUFFER_READ); - mp_get_buffer_raise(args[4], &pwdinfo, MP_BUFFER_READ); - - int min_profile_id = (int)HELIOS_PROFILE_IDX_MIN; - int max_profile_id = (int)HELIOS_PROFILE_IDX_MAX; - - if ((profile_id < min_profile_id) || (profile_id > max_profile_id)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, profileID should be in [%d,%d]."), min_profile_id, max_profile_id); - } - if ((ip_type < 0) || (ip_type > HELIOS_PDP_TYPE_NUM - 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, ipType should be in [0~%d]."), HELIOS_PDP_TYPE_NUM - 1); - } - if ((auth_type < 0) || (auth_type > HELIOS_AUTH_TYPE_NUM - 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, authType should be in [0~%d]."), HELIOS_AUTH_TYPE_NUM - 1); - } - if (apninfo.len > HELIOS_APN_LEN_MAX) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, the length of apn should be no more than [%d] bytes."), HELIOS_APN_LEN_MAX); - } - if (usrinfo.len > HELIOS_USR_LEN_MAX) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, the length of username should be no more than [%d] bytes."), HELIOS_USR_LEN_MAX); - } - if (pwdinfo.len > HELIOS_PWD_LEN_MAX) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, the length of password should be no more than [%d] bytes."), HELIOS_PWD_LEN_MAX); - } - - MOD_DATACALL_LOG("[datacall] profile_idx=%d, ip_version=%d, auth_type=%d\r\n", profile_id, ip_type, auth_type); - MOD_DATACALL_LOG("[datacall] anp_name=%s, usr_name=%s, password=%s\r\n", apninfo.buf, usrinfo.buf, pwdinfo.buf); - - Helios_DataCallStartStruct DataCallStartStruct = {0}; - DataCallStartStruct.ip_type = (int32_t)ip_type; - DataCallStartStruct.auth = (int32_t)auth_type; - snprintf(DataCallStartStruct.apn, sizeof(DataCallStartStruct.apn), "%s", (char *)apninfo.buf); - snprintf(DataCallStartStruct.user, sizeof(DataCallStartStruct.user), "%s", (char *)usrinfo.buf); - snprintf(DataCallStartStruct.pwd, sizeof(DataCallStartStruct.pwd), "%s", (char *)pwdinfo.buf); - - int cur_simid = _get_current_simid(); - if (n_args ==7) { - cur_simid = mp_obj_get_int(args[6]); - } - if ((cur_simid != 0) && (cur_simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); - } - - MP_THREAD_GIL_EXIT(); - ret = Helios_DataCall_Start(profile_id, cur_simid, &DataCallStartStruct); - MP_THREAD_GIL_ENTER(); - - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_datacall_start_obj, 5, 7, qpy_datacall_start); - - -static mp_obj_t qpy_datacall_stop(size_t n_args, const mp_obj_t *args) -{ - int ret = 0; - int profile_id = mp_obj_get_int(args[0]); - int ip_type = mp_obj_get_int(args[1]); - int cur_simid = _get_current_simid(); - - int min_profile_id = (int)HELIOS_PROFILE_IDX_MIN; - int max_profile_id = (int)HELIOS_PROFILE_IDX_MAX; - - if ((profile_id < min_profile_id) || (profile_id > max_profile_id)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, profileID should be in [%d,%d]."), min_profile_id, max_profile_id); - } - if ((ip_type < 0) || (ip_type > 2)) - { - mp_raise_ValueError(MP_ERROR_TEXT("invalid value, ipTpye should be in [0,2].")); - } - if (n_args ==3) { - cur_simid = mp_obj_get_int(args[2]); - } - if ((cur_simid != 0) && (cur_simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); - } - MP_THREAD_GIL_EXIT(); - ret = Helios_DataCall_Stop((int32_t)profile_id, cur_simid, (int32_t)ip_type); - MP_THREAD_GIL_ENTER(); - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_datacall_stop_obj, 2, 3, qpy_datacall_stop); - - -/*=============================================================================*/ -/* FUNCTION: qpy_datacall_set_autoconnect */ -/*=============================================================================*/ -/*!@brief : set auto connect - * @profile_idx [in] profile_idx, 1~7 - * @enable [in] 0-disable, 1-enable - * @return : - * - 0--successful - * - -1--error - */ -/*=============================================================================*/ -static mp_obj_t qpy_datacall_set_autoconnect(size_t n_args, const mp_obj_t *args) -{ - int ret = 0; - int profile_id = mp_obj_get_int(args[0]); - bool enable = mp_obj_is_true(args[1]); - - int min_profile_id = (int)HELIOS_PROFILE_IDX_MIN; - int max_profile_id = (int)HELIOS_PROFILE_IDX_MAX; - - if ((profile_id < min_profile_id) || (profile_id > max_profile_id)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, profileID should be in [%d,%d]."), min_profile_id, max_profile_id); - } - int cur_simid = _get_current_simid(); - if (n_args ==3) { - cur_simid = mp_obj_get_int(args[2]); - } - if ((cur_simid != 0) && (cur_simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); - } - ret = Helios_DataCall_SetAutoConnect((int32_t)profile_id, cur_simid, enable); - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_datacall_set_autoconnect_obj, 1, 3, qpy_datacall_set_autoconnect); - - -/*=============================================================================*/ -/* FUNCTION: qpy_datacall_set_asynmode */ -/*=============================================================================*/ -/*!@brief : Set asynchronous mode to datacall - * @mode [in] 0-disable, 1-enable - * @return : - * - 0--successful - * - -1--error - */ -/*=============================================================================*/ -static mp_obj_t qpy_datacall_set_asynmode(mp_obj_t mode) -{ - bool enable = mp_obj_is_true(mode); - int cur_simid = _get_current_simid(); - Helios_DataCall_SetAsynMode((int32_t)Helios_DataCall_GetCurrentPDP(), cur_simid, enable); - return mp_obj_new_int(0); -} -static MP_DEFINE_CONST_FUN_OBJ_1(qpy_datacall_set_asynmode_obj, qpy_datacall_set_asynmode); - - -static mp_obj_t qpy_datacall_get_info(size_t n_args, const mp_obj_t *args) -{ - int ret = 0; - int profile_id = mp_obj_get_int(args[0]); - int ip_type = mp_obj_get_int(args[1]); - char ip4_ip_addr[16] = {0}; - char ip4_pri_dns[16] = {0}; - char ip4_sec_dns[16] = {0}; - char ip6_ip_addr[64] = {0}; - char ip6_pri_dns[64] = {0}; - char ip6_sec_dns[64] = {0}; - Helios_DataCallInfoStruct info = {0}; - int min_profile_id = (int)HELIOS_PROFILE_IDX_MIN; - int max_profile_id = (int)HELIOS_PROFILE_IDX_MAX; - - if ((profile_id < min_profile_id) || (profile_id > max_profile_id)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, profileID should be in [%d,%d]."), min_profile_id, max_profile_id); - } - if ((ip_type < 0) || (ip_type > HELIOS_PDP_TYPE_NUM - 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, ipType should be in [0~%d]."), HELIOS_PDP_TYPE_NUM - 1); - } - info.ip_version = ip_type; - int cur_simid = _get_current_simid(); - if (n_args ==3) { - cur_simid = mp_obj_get_int(args[2]); - } - if ((cur_simid != 0) && (cur_simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); - } - MP_THREAD_GIL_EXIT(); - ret = Helios_DataCall_GetInfo(profile_id, cur_simid, &info); - MP_THREAD_GIL_ENTER(); - if (0 == ret) - { - inet_ntop(AF_INET, &info.v4.addr.ip, ip4_ip_addr, sizeof(ip4_ip_addr)); - inet_ntop(AF_INET, &info.v4.addr.pri_dns, ip4_pri_dns, sizeof(ip4_pri_dns)); - inet_ntop(AF_INET, &info.v4.addr.sec_dns, ip4_sec_dns, sizeof(ip4_sec_dns)); - inet_ntop(AF_INET6, &info.v6.addr.ip, ip6_ip_addr, sizeof(ip6_ip_addr)); - inet_ntop(AF_INET6, &info.v6.addr.pri_dns, ip6_pri_dns, sizeof(ip6_pri_dns)); - inet_ntop(AF_INET6, &info.v6.addr.sec_dns, ip6_sec_dns, sizeof(ip6_sec_dns)); - - mp_obj_t ip4_list[5] = { - mp_obj_new_int(info.v4.state), - mp_obj_new_int(info.v4.reconnect), - - mp_obj_new_str(ip4_ip_addr, strlen(ip4_ip_addr)), - mp_obj_new_str(ip4_pri_dns, strlen(ip4_pri_dns)), - mp_obj_new_str(ip4_sec_dns, strlen(ip4_sec_dns)), - }; - mp_obj_t ip6_list[5] = { - mp_obj_new_int(info.v6.state), - mp_obj_new_int(info.v6.reconnect), - - mp_obj_new_str(ip6_ip_addr, strlen(ip6_ip_addr)), - mp_obj_new_str(ip6_pri_dns, strlen(ip6_pri_dns)), - mp_obj_new_str(ip6_sec_dns, strlen(ip6_sec_dns)), - }; - - if (ip_type == 0) - { - mp_obj_t tuple[3] = { - mp_obj_new_int(info.profile_idx), - mp_obj_new_int(info.ip_version), - mp_obj_new_list(5, ip4_list), - }; - return mp_obj_new_tuple(3, tuple); - } - else if (ip_type == 1) - { - mp_obj_t tuple[3] = { - mp_obj_new_int(info.profile_idx), - mp_obj_new_int(info.ip_version), - mp_obj_new_list(5, ip6_list), - }; - return mp_obj_new_tuple(3, tuple); - } - else if (ip_type == 2) - { - mp_obj_t tuple[4] = { - mp_obj_new_int(info.profile_idx), - mp_obj_new_int(info.ip_version), - mp_obj_new_list(5, ip4_list), - mp_obj_new_list(5, ip6_list), - }; - - return mp_obj_new_tuple(4, tuple); - } - } - return mp_obj_new_int(ret); -} - -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_datacall_get_info_obj, 1, 3, qpy_datacall_get_info); - - - -static c_callback_t * g_usr_callback = NULL; - -static void datacall_callback(int32_t profile_idx, uint8_t sim_id, int32_t nw_status) -{ - - MOD_DATACALL_LOG("[datacall] pdp = %d, nwsta = %d\r\n", profile_idx, nw_status); - if (g_usr_callback) - { - st_CallBack_Datacall *Datacall_param = (st_CallBack_Datacall *)malloc(sizeof(st_CallBack_Datacall)); - if(NULL != Datacall_param) - { - Datacall_param->profile_idx = profile_idx; - Datacall_param->nw_status = nw_status; - Datacall_param->sim_id = sim_id; - Datacall_param->callback = *g_usr_callback; - - qpy_send_msg_to_callback_deal_thread(CALLBACK_TYPE_ID_DATACALL, Datacall_param); - } - } -} - - -/*=============================================================================*/ -/* FUNCTION: qpy_datacall_register_usr_callback */ -/*=============================================================================*/ -/*!@brief : register the callback function for user - * @user_cb [in] callback function - * @return : - * - 0--successful - * - -1--error - */ -/*=============================================================================*/ -static mp_obj_t qpy_datacall_register_usr_callback(mp_obj_t callback) -{ - static c_callback_t cb = {0}; - memset(&cb, 0, sizeof(c_callback_t)); - cb.arg = mp_obj_new_tuple(3, NULL); - g_usr_callback = &cb; - mp_sched_schedule_callback_register(g_usr_callback, callback); - - Helios_DataCallInitStruct DataCallInitStruct = {datacall_callback}; - int cur_simid = _get_current_simid(); - Helios_DataCall_Init((int32_t)Helios_DataCall_GetCurrentPDP(), cur_simid, &DataCallInitStruct); - return mp_obj_new_int(0); -} -static MP_DEFINE_CONST_FUN_OBJ_1(qpy_register_usr_callback_obj, qpy_datacall_register_usr_callback); - -static mp_obj_t qpy_datacall_get_pdp_range(void) -{ - uint32_t min = Helios_DataCall_GetProfileIdxMin(); - uint32_t max = Helios_DataCall_GetProfileIdxMax(); - mp_obj_t tuple[2] = - { - mp_obj_new_int(min), - mp_obj_new_int(max) - }; - - return mp_obj_new_tuple(2, tuple); -} -static MP_DEFINE_CONST_FUN_OBJ_0(qpy_get_pdp_range_obj, qpy_datacall_get_pdp_range); - -static mp_obj_t qpy_datacall_get_range(mp_obj_t kind) -{ - int para_kind = mp_obj_get_int(kind); - - if (para_kind == 0) //apn - { - return mp_obj_new_int(HELIOS_APN_LEN_MAX); - } - else if (para_kind == 1) //password - { - return mp_obj_new_int(HELIOS_PWD_LEN_MAX); - } - else if (para_kind == 2) //usrname - { - return mp_obj_new_int(HELIOS_USR_LEN_MAX); - } - else if (para_kind == 3) //pid - { - return mp_obj_new_int(HELIOS_PROFILE_IDX_MAX); - } - else if (para_kind == 4) //iptype - { - return mp_obj_new_int(HELIOS_PDP_TYPE_NUM); - } - else if (para_kind == 5) //authtype - { - return mp_obj_new_int(HELIOS_AUTH_TYPE_NUM); - } - else - { - return mp_obj_new_int(-1); - } -} -static MP_DEFINE_CONST_FUN_OBJ_1(qpy_datacall_get_range_obj, qpy_datacall_get_range); - -static mp_obj_t qpy_datacall_get_apn(size_t n_args, const mp_obj_t *args) -{ -#if defined(PLAT_ASR) || defined(PLAT_Unisoc) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc)|| defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) \ - || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_ASR_1602) || defined(PLAT_Unisoc_8910_R06) - int sim_id = mp_obj_get_int(args[0]); - int ret = 0; - char apn[99+1] = {0}; - if (sim_id != 0) - { - mp_raise_ValueError(MP_ERROR_TEXT("invalid simid.")); - } - if (n_args == 1) - { - MP_THREAD_GIL_EXIT(); - ret = Helios_DataCall_GetApn(2, sim_id, apn); - MP_THREAD_GIL_ENTER(); - if (ret == 0) - { - return mp_obj_new_str(apn, strlen(apn)); - } - return mp_obj_new_int(-1); - } - else if (n_args == 2) - { - int pid = mp_obj_get_int(args[1]); - MP_THREAD_GIL_EXIT(); - ret = Helios_DataCall_GetApn(3, sim_id, apn, pid); - MP_THREAD_GIL_ENTER(); - if (ret == 0) - { - return mp_obj_new_str(apn, strlen(apn)); - } - return mp_obj_new_int(-1); - } - else - { - mp_raise_ValueError(MP_ERROR_TEXT("invalid value, The number of parameters cannot be greater than 2.")); - } -#else - mp_raise_ValueError(MP_ERROR_TEXT("NOT SUPPORT")); -#endif -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_datacall_get_apn_obj, 1, 2, qpy_datacall_get_apn); - -#if defined(PLAT_ASR) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_Unisoc_8910_R06) -static mp_obj_t qpy_datacall_set_dns_server(size_t n_args, const mp_obj_t *args) -{ - int profile_id = mp_obj_get_int(args[0]); - int sim_id = mp_obj_get_int(args[1]); - - mp_buffer_info_t new_pri_dns = {0}; - mp_buffer_info_t new_sec_dns = {0}; - mp_get_buffer_raise(args[2], &new_pri_dns, MP_BUFFER_READ); - mp_get_buffer_raise(args[3], &new_sec_dns, MP_BUFFER_READ); - - int min_profile_id = (int)HELIOS_PROFILE_IDX_MIN; - int max_profile_id = (int)HELIOS_PROFILE_IDX_MAX; - - if ((profile_id < min_profile_id) || (profile_id > max_profile_id)) - { - mp_raise_msg_varg(&mp_type_ValueError, "invalid value, profileID should be in [%d,%d].", min_profile_id, max_profile_id); - } - - char new_pri[128]; - char new_sec[128]; - memset(&new_pri, 0, sizeof(new_pri)); - memset(&new_sec, 0, sizeof(new_sec)); - - memcpy(new_pri, new_pri_dns.buf, new_pri_dns.len); - memcpy(new_sec, new_sec_dns.buf, new_sec_dns.len); - - int ret = 0; - MP_THREAD_GIL_EXIT(); - ret = Helios_DataCall_SetDnsServer(profile_id, sim_id, new_pri, new_sec); - MP_THREAD_GIL_ENTER(); - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_datacall_set_dns_server_obj, 4, 4, qpy_datacall_set_dns_server); -#endif - -static mp_obj_t qpy_datacall_get_date_speed(size_t n_args, const mp_obj_t *args) -{ - uint32_t rx = 0, tx = 0; -#if defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) - MP_THREAD_GIL_EXIT(); - Helios_DataCall_GetDataSpeed(&rx, &tx); - MP_THREAD_GIL_ENTER(); -#endif - mp_obj_t date_speed[2] = { - mp_obj_new_int_from_uint(rx), //bps - mp_obj_new_int_from_uint(tx), //bps - }; - return mp_obj_new_tuple(2,date_speed); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_datacall_get_date_speed_obj, 0, 0, qpy_datacall_get_date_speed); - -static mp_obj_t qpy_datacall_get_address_info(size_t n_args, const mp_obj_t *args) -{ - int profile_id = mp_obj_get_int(args[0]); - int ip_type = 0; - - if (n_args == 2) - { - ip_type = mp_obj_get_int(args[1]); - } - -#if MICROPY_QPY_MODULE_WANINFO - struct netif* netif_cfg = netif_get_by_cid(profile_id-1); - - if(netif_cfg) - { - static uint8_t g_mac[6] = {0}; - g_mac[0] = netif_cfg->hwaddr[0]; - g_mac[1] = netif_cfg->hwaddr[1]; - g_mac[2] = netif_cfg->hwaddr[2]; - g_mac[3] = netif_cfg->hwaddr[3]; - g_mac[4] = netif_cfg->hwaddr[4]; - g_mac[5] = netif_cfg->hwaddr[5]; - - char mac[64] = {0}; - sprintf(mac, "%02X-%02X-%02X-%02X-%02X-%02X", g_mac[0], g_mac[1], g_mac[2], g_mac[3], g_mac[4], g_mac[5]); - - if (ip_type == 0)//IPV4 - { - char mask[16] = {0}; - char gw[16] = {0}; - - struct sockaddr_in local_v4; - - local_v4.sin_addr.s_addr = netif_cfg->netmask.addr; - inet_ntop(AF_INET, &local_v4.sin_addr.s_addr, mask, sizeof(mask)); - - local_v4.sin_addr.s_addr = netif_cfg->gw.addr; - inet_ntop(AF_INET, &local_v4.sin_addr.s_addr, gw, sizeof(gw)); - - mp_obj_t addrinfo_tuple[3] = { - mp_obj_new_str(mac, strlen(mac)), - mp_obj_new_str(mask, strlen(mask)), - mp_obj_new_str(gw, strlen(gw)) - }; - - return mp_obj_new_tuple(3,addrinfo_tuple); - } - else if (ip_type == 1)//IPV6 - { - struct sockaddr_in6 local_v6; - char ip6_gw[64] = {0}; - ip6_addr_t * ip6_addr_ptr = NULL; - - ip6_addr_ptr = &(netif_cfg->ip6_gw); - memcpy(&local_v6.sin6_addr, ip6_addr_ptr, sizeof(ip6_addr_t)); - inet_ntop(AF_INET6, &local_v6.sin6_addr, ip6_gw, sizeof(ip6_gw)); - - mp_obj_t addrinfo_tuple[2] = { - mp_obj_new_str(mac, strlen(mac)), - mp_obj_new_str(ip6_gw, strlen(ip6_gw)) - }; - - return mp_obj_new_tuple(2,addrinfo_tuple); - } - else if (ip_type == 2)//IPV4&6 - { - char mask[16] = {0}; - char gw[16] = {0}; - - struct sockaddr_in local_v4; - - local_v4.sin_addr.s_addr = netif_cfg->netmask.addr; - inet_ntop(AF_INET, &local_v4.sin_addr.s_addr, mask, sizeof(mask)); - - local_v4.sin_addr.s_addr = netif_cfg->gw.addr; - inet_ntop(AF_INET, &local_v4.sin_addr.s_addr, gw, sizeof(gw)); - - mp_obj_t addrinfo_tuple[3] = { - mp_obj_new_str(mac, strlen(mac)), - mp_obj_new_str(mask, strlen(mask)), - mp_obj_new_str(gw, strlen(gw)) - }; - - char ip6_gw[64] = {0}; - struct sockaddr_in6 local_v6; - ip6_addr_t * ip6_addr_ptr = NULL; - - ip6_addr_ptr = &(netif_cfg->ip6_gw); - memcpy(&local_v6.sin6_addr, ip6_addr_ptr, sizeof(ip6_addr_t)); - inet_ntop(AF_INET6, &local_v6.sin6_addr, ip6_gw, sizeof(ip6_gw)); - - mp_obj_t addr6info_tuple[2] = { - mp_obj_new_str(mac, strlen(mac)), - mp_obj_new_str(ip6_gw, strlen(ip6_gw)) - }; - - mp_obj_t ipconfig_list[2] = { - mp_obj_new_tuple(3, addrinfo_tuple), - mp_obj_new_tuple(2, addr6info_tuple) - }; - return mp_obj_new_list(2, ipconfig_list); - } - } -#else - (void)profile_id;(void)ip_type; -#endif - - return mp_obj_new_int(-1); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_datacall_get_address_info_obj, 1, 2, qpy_datacall_get_address_info); - -static mp_obj_t qpy_datacall_get_sim_info(size_t n_args, const mp_obj_t *args) -{ -#if MICROPY_QPY_MODULE_WANINFO - int sim_id = mp_obj_get_int(args[0]); - Helios_DataCallSimUsed info; - - Helios_DataCall_GetSimUsed(sim_id, &info); - - mp_obj_t siminfo_tuple[4] = { - mp_obj_new_int(info.recv_MBytes_sim), - mp_obj_new_int(info.recv_Bytes_sim), - mp_obj_new_int(info.used_MBytes_sim), - mp_obj_new_int(info.used_Bytes_sim) - }; - - return mp_obj_new_tuple(4,siminfo_tuple); -#endif - - return mp_obj_new_int(-1); -}static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_datacall_get_sim_info_obj, 1, 1, qpy_datacall_get_sim_info); - -static mp_obj_t qpy_module_datacall_deinit(void) -{ - g_usr_callback = NULL; - MOD_DATACALL_LOG("module datacall deinit.\r\n"); -#if defined(PLAT_ASR) || defined(PLAT_Unisoc) || defined(PLAT_Qualcomm) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_Unisoc_8910_R06) - Helios_DataCall_Deinit(); -#endif - return mp_obj_new_int(0); -} -static MP_DEFINE_CONST_FUN_OBJ_0(qpy_module_datacall_deinit_obj, qpy_module_datacall_deinit); - - -static mp_obj_t qpy_datacall_use_attach_apn(size_t n_args, const mp_obj_t *args) -{ -#if defined(PLAT_ASR) - int ret = 0; - bool is_using_attach_apn = false; - if (n_args == 1) { - is_using_attach_apn = mp_obj_is_true(args[0]); - MP_THREAD_GIL_EXIT(); - ret = Helios_DataCall_SetIsUseAttachApn(is_using_attach_apn ? 0 : 1); - MP_THREAD_GIL_ENTER(); - return mp_obj_new_int(ret); - } else { - MP_THREAD_GIL_EXIT(); - is_using_attach_apn = Helios_DataCall_GetIsUseAttachApn(); - MP_THREAD_GIL_ENTER(); - return mp_obj_new_bool(!is_using_attach_apn); - } -#else - mp_raise_ValueError(MP_ERROR_TEXT("NOT SUPPORT")); -#endif -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_datacall_use_attach_apn_obj, 0, 1, qpy_datacall_use_attach_apn); - - -static const mp_rom_map_elem_t mp_module_datacall_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_dial) }, - { MP_ROM_QSTR(MP_QSTR___qpy_module_deinit__), MP_ROM_PTR(&qpy_module_datacall_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR_setPDPContext), MP_ROM_PTR(&qpy_datacall_set_pdp_context_obj) }, - { MP_ROM_QSTR(MP_QSTR_getPDPContext), MP_ROM_PTR(&qpy_datacall_get_pdp_context_obj) }, - { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&qpy_datacall_start_obj) }, - { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&qpy_datacall_stop_obj) }, - { MP_ROM_QSTR(MP_QSTR_setAutoConnect), MP_ROM_PTR(&qpy_datacall_set_autoconnect_obj) }, - { MP_ROM_QSTR(MP_QSTR_getInfo), MP_ROM_PTR(&qpy_datacall_get_info_obj) }, - { MP_ROM_QSTR(MP_QSTR_setCallback), MP_ROM_PTR(&qpy_register_usr_callback_obj) }, - { MP_ROM_QSTR(MP_QSTR_setAsynMode), MP_ROM_PTR(&qpy_datacall_set_asynmode_obj) }, - { MP_ROM_QSTR(MP_QSTR_getPdpRange), MP_ROM_PTR(&qpy_get_pdp_range_obj) }, - { MP_ROM_QSTR(MP_QSTR_getRange), MP_ROM_PTR(&qpy_datacall_get_range_obj) }, - { MP_ROM_QSTR(MP_QSTR_getApn), MP_ROM_PTR(&qpy_datacall_get_apn_obj) }, - #if defined(PLAT_ASR) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_Unisoc_8910_R06) - { MP_ROM_QSTR(MP_QSTR_setDnsserver), MP_ROM_PTR(&qpy_datacall_set_dns_server_obj) }, - #endif - { MP_ROM_QSTR(MP_QSTR_useAttachApn), MP_ROM_PTR(&qpy_datacall_use_attach_apn_obj) }, - { MP_ROM_QSTR(MP_QSTR_getSpeed), MP_ROM_PTR(&qpy_datacall_get_date_speed_obj) }, - { MP_ROM_QSTR(MP_QSTR_getAddressinfo), MP_ROM_PTR(&qpy_datacall_get_address_info_obj) }, - { MP_ROM_QSTR(MP_QSTR_getSiminfo), MP_ROM_PTR(&qpy_datacall_get_sim_info_obj) }, -}; -static MP_DEFINE_CONST_DICT(mp_module_datacall_globals, mp_module_datacall_globals_table); - - -const mp_obj_module_t mp_module_dial = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t *)&mp_module_datacall_globals, -}; - -MP_REGISTER_MODULE(MP_QSTR_dial, mp_module_dial); -#endif /* MICROPY_QPY_MODULE_DATACALL */ diff --git a/ports/quectel/moddatacall.h b/ports/quectel/moddatacall.h deleted file mode 100644 index 880548c5d494f..0000000000000 --- a/ports/quectel/moddatacall.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020-2021 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 __MODDATACALL_H__ -#define __MODDATACALL_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef void(* nw_status_cb)(int profile_idx, int nw_status); - - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/ports/quectel/moddev.c b/ports/quectel/moddev.c deleted file mode 100644 index aa62f787b5c40..0000000000000 --- a/ports/quectel/moddev.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020-2021 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 "obj.h" -#include "runtime.h" -#include "mphalport.h" - -#if MICROPY_QPY_MODULE_MODEM - -#include "helios_dev.h" - - -static mp_obj_t queclib_dev_product_id() -{ - char product_id_str[64] = {0}; - int ret = Helios_Dev_GetPID((void *)product_id_str, sizeof(product_id_str)); - if(ret == 0) - { - return mp_obj_new_str(product_id_str, strlen(product_id_str)); - } - return mp_obj_new_int(-1); -} - -static MP_DEFINE_CONST_FUN_OBJ_0(queclib_dev_product_id_obj, queclib_dev_product_id); - -extern int _get_current_simid(void); - -static mp_obj_t queclib_dev_serial_number(size_t n_args, const mp_obj_t *args) -{ -#if !defined(PLAT_aic8800m40) && !defined(PLAT_ECR6600) && !defined(PLAT_SONY_ALT1350) - int cur_simid = _get_current_simid(); - if (n_args ==1) { - cur_simid = mp_obj_get_int(args[0]); - } - if ((cur_simid != 0) && (cur_simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); - } -#endif - char serial_number_str[64] = {0}; - #if MICROPY_QPY_MODULE_DSDS - int ret = Helios_Dev_GetSN((void *)serial_number_str, sizeof(serial_number_str), cur_simid); - #else - int ret = Helios_Dev_GetSN((void *)serial_number_str, sizeof(serial_number_str),0); - #endif - if(ret == 0) - { - return mp_obj_new_str(serial_number_str, strlen(serial_number_str)); - } - return mp_obj_new_int(-1); -} - -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(queclib_dev_serial_number_obj, 0, 1, queclib_dev_serial_number); - -static mp_obj_t queclib_dev_model() -{ - char model_str[64] = {0}; - int ret = Helios_Dev_GetModel((void *)model_str, sizeof(model_str)); - if(ret == 0) - { - return mp_obj_new_str(model_str, strlen(model_str)); - } - return mp_obj_new_int(-1); -} - -static MP_DEFINE_CONST_FUN_OBJ_0(queclib_dev_model_obj, queclib_dev_model); - - -mp_obj_t queclib_dev_fw_version() -{ - char fw_version_str[64] = {0}; - int ret = Helios_Dev_GetFwVersion((void *)fw_version_str, sizeof(fw_version_str)); - if(ret == 0) - { - return mp_obj_new_str(fw_version_str, strlen(fw_version_str)); - } - return mp_obj_new_int(-1); -} - -static MP_DEFINE_CONST_FUN_OBJ_0(queclib_dev_fw_version_obj, queclib_dev_fw_version); - - -#if !defined(PLAT_aic8800m40) && !defined(PLAT_ECR6600) - -static mp_obj_t queclib_dev_imei(size_t n_args, const mp_obj_t *args) -{ - #if !defined(PLAT_SONY_ALT1350) - int cur_simid = _get_current_simid(); - #else - int cur_simid = 0; - #endif - if (n_args ==1) { - cur_simid = mp_obj_get_int(args[0]); - } - if ((cur_simid != 0) && (cur_simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); - } - //the imei length is 15-17 bytes - char imei_str[19] = {0}; -#if MICROPY_QPY_MODULE_DSDS - int ret = Helios_Dev_GetIMEI((void *)imei_str, sizeof(imei_str), cur_simid); -#else - #if MICROPY_QPY_MODULE_DUALIMEI - cur_simid = (n_args ==1) ? cur_simid + 2 : 0; - int ret = Helios_Dev_GetIMEI((void *)imei_str, sizeof(imei_str),cur_simid); - #else - int ret = Helios_Dev_GetIMEI((void *)imei_str, sizeof(imei_str),0); - #endif -#endif - if(ret == 0) - { - return mp_obj_new_str(imei_str, strlen(imei_str)); - } - return mp_obj_new_int(-1); -} - -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(queclib_dev_imei_obj, 0, 1, queclib_dev_imei); -#endif - -#if defined (PLAT_Qualcomm) -static mp_obj_t queclib_dev_backup() -{ - MP_THREAD_GIL_EXIT(); - int ret = Helios_Dev_Backup(); - MP_THREAD_GIL_ENTER(); - if( ret != 0 ) return mp_obj_new_int(-1); - return mp_obj_new_int(0); -} - -static MP_DEFINE_CONST_FUN_OBJ_0(queclib_dev_backup_obj, queclib_dev_backup); - -static mp_obj_t queclib_dev_backup_status() -{ - Helios_DevBackupStatusStruct backup_status_info = {0}; - - int ret = Helios_Dev_Backup_Status(&backup_status_info); - if( ret == 0 ) - { - mp_obj_t info[3] = - { - mp_obj_new_int(backup_status_info.backup_valid), - mp_obj_new_int(backup_status_info.backup_cnt), - mp_obj_new_int(backup_status_info.restore_cnt), - }; - return mp_obj_new_tuple(3, info); - } - return mp_obj_new_int(-1); -} - -static MP_DEFINE_CONST_FUN_OBJ_0(queclib_dev_backup_status_obj, queclib_dev_backup_status); - -static mp_obj_t set_usbmode(mp_obj_t usbmode) { - int mode = mp_obj_get_int(usbmode); - extern int Helios_Dev_SetUSBMode(int mode); - return mp_obj_new_int(Helios_Dev_SetUSBMode(mode)); -} - -static MP_DEFINE_CONST_FUN_OBJ_1(set_usbmode_obj, set_usbmode); - -//forrest.liu@20220112 add for main uart change from AT to general uart -extern void Helios_Dev_Main_UART_Enable_Set(int onoff); -extern int Helios_Dev_Main_UART_Enable_Get(void); - -static mp_obj_t main_uart_enable_set(mp_obj_t onoff) { - int mode = mp_obj_get_int(onoff); - Helios_Dev_Main_UART_Enable_Set(mode); - return mp_obj_new_int(0); -} - -static MP_DEFINE_CONST_FUN_OBJ_1(main_uart_enable_set_obj, main_uart_enable_set); - -static mp_obj_t main_uart_enable_get() { - int mode = Helios_Dev_Main_UART_Enable_Get(); - return mp_obj_new_int(mode); -} - -static MP_DEFINE_CONST_FUN_OBJ_0(main_uart_enable_get_obj, main_uart_enable_get); - -#endif - -#if defined(PLAT_ECR6600) || defined(PLAT_aic8800m40) - -static mp_obj_t queclib_dev_mac() -{ - char serial_number_str[64] = {0}; - int ret = Helios_Dev_GetMAC((void *)serial_number_str, sizeof(serial_number_str)); - sprintf(serial_number_str,"%02x:%02x:%02x:%02x:%02x:%02x", - serial_number_str[0]&0xff, - serial_number_str[1]&0xff, - serial_number_str[2]&0xff, - serial_number_str[3]&0xff, - serial_number_str[4]&0xff, - serial_number_str[5]&0xff); - - if(ret == 0) - { - return mp_obj_new_str(serial_number_str, strlen(serial_number_str)); - } - - return mp_obj_new_int(-1); -} - -static MP_DEFINE_CONST_FUN_OBJ_0(queclib_dev_mac_obj, queclib_dev_mac); -#endif - - -#if defined(BOARD_EG915ULA_AC_USBUP) || defined(BOARD_EG915UCN_AC_USBUP) \ - || defined(BOARD_EG915UEU_AC_USBUP) || defined(BOARD_EG915UEC_AC_USBUP) -int Helios_Dev_SetIMEI(void *buffer); - -static mp_obj_t queclib_dev_imei_set(mp_obj_t imei) { - char *imei_str = (char *)mp_obj_str_get_str(imei); - MP_THREAD_GIL_EXIT(); - int ret = Helios_Dev_SetIMEI(imei_str); - MP_THREAD_GIL_ENTER(); - if(ret != 0) - { - return mp_obj_new_int(-1); - } - return mp_obj_new_int(0); -} - -static MP_DEFINE_CONST_FUN_OBJ_1(queclib_dev_imei_set_obj, queclib_dev_imei_set); -#endif - -static const mp_rom_map_elem_t mp_module_modem_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_modem) }, -#if !defined(PLAT_aic8800m40) - { MP_ROM_QSTR(MP_QSTR_getDevSN), MP_ROM_PTR(&queclib_dev_serial_number_obj) }, -#endif -#if !defined(PLAT_aic8800m40) && !defined(PLAT_ECR6600) - { MP_ROM_QSTR(MP_QSTR_getDevImei), MP_ROM_PTR(&queclib_dev_imei_obj) }, -#endif - { MP_ROM_QSTR(MP_QSTR_getDevModel), MP_ROM_PTR(&queclib_dev_model_obj) }, - { MP_ROM_QSTR(MP_QSTR_getDevFwVersion), MP_ROM_PTR(&queclib_dev_fw_version_obj) }, - { MP_ROM_QSTR(MP_QSTR_getDevProductId), MP_ROM_PTR(&queclib_dev_product_id_obj) }, - -#if defined (PLAT_Qualcomm) - { MP_ROM_QSTR(MP_QSTR_backup), MP_ROM_PTR(&queclib_dev_backup_obj) }, - { MP_ROM_QSTR(MP_QSTR_backupStatus), MP_ROM_PTR(&queclib_dev_backup_status_obj) }, - { MP_ROM_QSTR(MP_QSTR_setUSBMode), MP_ROM_PTR(&set_usbmode_obj) }, - { MP_ROM_QSTR(MP_QSTR_main_uart_enable_set), MP_ROM_PTR(&main_uart_enable_set_obj) }, - { MP_ROM_QSTR(MP_QSTR_main_uart_enable_get), MP_ROM_PTR(&main_uart_enable_get_obj) }, -#endif -#if defined(BOARD_EG915ULA_AC_USBUP) || defined(BOARD_EG915UCN_AC_USBUP) \ - || defined(BOARD_EG915UEU_AC_USBUP) || defined(BOARD_EG915UEC_AC_USBUP) - { MP_ROM_QSTR(MP_QSTR_setDevImei), MP_ROM_PTR(&queclib_dev_imei_set_obj) }, -#endif -#if defined(PLAT_ECR6600) || defined(PLAT_aic8800m40) - { MP_ROM_QSTR(MP_QSTR_getDevMAC), MP_ROM_PTR(&queclib_dev_mac_obj) }, -#endif -}; -static MP_DEFINE_CONST_DICT(mp_module_modem_globals, mp_module_modem_globals_table); - - -const mp_obj_module_t mp_module_modem = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t *)&mp_module_modem_globals, -}; - -MP_REGISTER_MODULE(MP_QSTR_modem, mp_module_modem); -#endif /* MICROPY_PORT_BUILTIN_MODULES_MODEM */ diff --git a/ports/quectel/modexample.c b/ports/quectel/modexample.c deleted file mode 100644 index ceb1400e72636..0000000000000 --- a/ports/quectel/modexample.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020-2021 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 -#include "py/compile.h" -#include "py/runtime0.h" -#include "py/nlr.h" -#include "py/objlist.h" -#include "py/objstr.h" -#include "py/runtime.h" -#include "py/mperrno.h" -#include "py/mphal.h" -#include "py/stream.h" -#include "shared/runtime/pyexec.h" -#include "shared/runtime/interrupt_char.h" - - -#if MICROPY_QPY_MODULE_EXAMPLE - -static mp_obj_t example_exec(const mp_obj_t arg0) -{ - int ret = 0; - - mp_buffer_info_t bufinfo; - char fname[128] = {0}; - char path[128] = {0}; - mp_get_buffer_raise(arg0, &bufinfo, MP_BUFFER_READ); - - memcpy(path, bufinfo.buf, bufinfo.len); - - if(bufinfo.buf != NULL) - { - // Pawn 2021-01-18 for JIRA STASR3601-2428 begin - if (path[0] != '/') - { - snprintf(fname, sizeof(fname), "/%s", (char *)bufinfo.buf); - } - else - { - snprintf(fname, sizeof(fname), "%s", (char *)bufinfo.buf); - } - - ret = pyexec_file_if_exists(fname); - } - if ( ret == -1 ) - { - mp_raise_msg_varg(&mp_type_OSError, MP_ERROR_TEXT("File path error or not exist: [%s]"), (char *)bufinfo.buf); - } - #if MICROPY_PY_KBD_EXCEPTION - else if(ret == RET_KBD_INTERRUPT) - { - pyexec_system_exit = PYEXEC_FORCED_EXIT; - MAINPY_INTERRUPT_BY_KBD_FLAG_SET(); - mp_raise_msg_varg(&mp_type_SystemExit, MP_ERROR_TEXT("CTRL_C Interrupt")); - } - #endif - #if MICROPY_PY_SOFT_RESET - else if((ret & PYEXEC_SOFTRESET) == PYEXEC_SOFTRESET) - { - pyexec_system_exit = PYEXEC_FORCED_EXIT; - mp_raise_msg_varg(&mp_type_SystemExit, MP_ERROR_TEXT("SoftReset")); - } - #endif - // Pawn 2021-01-18 for JIRA STASR3601-2428 end - return mp_const_none; -} - - - -static MP_DEFINE_CONST_FUN_OBJ_1(example_exec_obj, example_exec); - - -static mp_obj_t example_initialize() -{ - static int initialized = 0; - if (!initialized) { - initialized = 1; - } - return mp_const_none; -} - -static MP_DEFINE_CONST_FUN_OBJ_0(example_initialize_obj, example_initialize); - -static const mp_rom_map_elem_t mp_module_example_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_example) }, - { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&example_initialize_obj) }, - { MP_ROM_QSTR(MP_QSTR_exec), MP_ROM_PTR(&example_exec_obj) }, - -}; - - -static MP_DEFINE_CONST_DICT(mp_module_example_globals, mp_module_example_globals_table); - - -const mp_obj_module_t example_module = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t *)&mp_module_example_globals, -}; - -MP_REGISTER_MODULE(MP_QSTR_example, example_module); -#endif /* MICROPY_QPY_MODULE_EXAMPLE */ diff --git a/ports/quectel/modfota.c b/ports/quectel/modfota.c deleted file mode 100644 index 6a656051a93ac..0000000000000 --- a/ports/quectel/modfota.c +++ /dev/null @@ -1,446 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020-2021 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/obj.h" -#include -#include "py/runtime.h" -#include "mphalport.h" -#include "gccollect.h" - - -#if MICROPY_QPY_MODULE_FOTA - -#include "helios_fota.h" -#include "helios_power.h" -#include "helios_debug.h" -#include "callbackdeal.h" -#include "shared/runtime/pyexec.h" - - -#define MOD_FOTA_LOG(msg, ...) custom_log(FOTA, msg, ##__VA_ARGS__) - -typedef struct _fota_obj_t { - mp_obj_base_t base; - int ctx; -}fota_obj_t; - -const mp_obj_type_t mp_fota_type; -static fota_obj_t *fota_self_obj = NULL; - -static char *temp_server_address1 = NULL; - -extern void Helios_Fota_SslConfig(char *rootCA, char *clientCert, char *clientKey); - -#if defined(PLAT_Qualcomm) || defined (PLAT_Unisoc) || defined(PLAT_ASR_1803s) || defined(PLAT_EIGEN) -extern int Helios_Fota_Download_Cancel(void); -extern int Helios_Fota_Reset_Disable(int flag); -extern int Helios_Fota_APN_Set(int ip_type, char *apn, char *user, char *pass); -#endif - -static mp_obj_t fota_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) -{ - if (fota_self_obj == NULL) - { - fota_self_obj = mp_obj_malloc_with_finaliser(fota_obj_t, &mp_fota_type); - } - fota_obj_t *self = fota_self_obj; - - self->base.type = &mp_fota_type; - self->ctx = Helios_Fota_Init(); - -#if defined (PLAT_ASR) || defined (PLAT_Unisoc) || defined(PLAT_Qualcomm) || defined(PLAT_ASR_1803s) || defined(PLAT_EIGEN) - const byte *key = NULL; - const byte *cert = NULL; - const byte *root_cert = NULL; -#if defined(PLAT_Qualcomm) || defined (PLAT_Unisoc) || defined(PLAT_ASR_1803s) || defined(PLAT_EIGEN) - int reset_disable = 0; -#endif - - if (n_args > 0 || n_kw > 0) - { - //ssl args - enum { ARG_key, ARG_cert, ARG_root_cert, ARG_reset_disable}; - - static const mp_arg_t allowed_args[] = { - { MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_root_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_reset_disable, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, - }; - - mp_map_t kw_args; - mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); - // parse args - mp_arg_val_t args_dest[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args, args, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args_dest); - - if (args_dest[ARG_key].u_obj != mp_const_none) - { - size_t key_len; - key = (const byte *)mp_obj_str_get_data(args_dest[ARG_key].u_obj, &key_len); - } - - if (args_dest[ARG_cert].u_obj != mp_const_none) - { - size_t cert_len; - cert = (const byte *)mp_obj_str_get_data(args_dest[ARG_cert].u_obj, &cert_len); - } - - if (args_dest[ARG_root_cert].u_obj != mp_const_none) - { - size_t root_cert_len; - root_cert = (const byte *)mp_obj_str_get_data(args_dest[ARG_root_cert].u_obj, &root_cert_len); - } - #if defined(PLAT_Qualcomm) || defined (PLAT_Unisoc) || defined(PLAT_ASR_1803s) || defined(PLAT_EIGEN) - if (args_dest[ARG_reset_disable].u_int != -1) - { - reset_disable = args_dest[ARG_reset_disable].u_int; - } - #endif - } -#if defined(PLAT_Qualcomm) || defined (PLAT_Unisoc) || defined(PLAT_ASR_1803s) || defined(PLAT_EIGEN) - Helios_Fota_Reset_Disable(reset_disable); -#endif - Helios_Fota_SslConfig((char *)(root_cert), (char *)(cert), (char *)(key)); -#endif - return MP_OBJ_FROM_PTR(self); -} - -static mp_obj_t fota_write(size_t n_args, const mp_obj_t *args) -{ - int ret; - int file_size; - - fota_obj_t *self = MP_OBJ_TO_PTR(args[0]); - - if(n_args > 2) - { - file_size = mp_obj_get_int(args[2]); - } - else - { - MOD_FOTA_LOG("*** input param invalid \r\n***"); - return mp_obj_new_int(-1); - } - - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); - - MOD_FOTA_LOG(" buff len : %d file_size : %d\r\n", bufinfo.len, file_size); - - MP_THREAD_GIL_EXIT(); - ret = Helios_Fota_PackageWrite(self->ctx, bufinfo.buf, bufinfo.len, (size_t)file_size); - MP_THREAD_GIL_ENTER(); - - if(ret) - { - MOD_FOTA_LOG("*** fota package write fail ***\r\n"); - return mp_obj_new_int(-1); - } - if(ret < 0) - { - MOD_FOTA_LOG("*** fota package file read fail ***\r\n"); - return mp_obj_new_int(-1); - } - - return mp_obj_new_int(0); -} -#if !defined(PLAT_RDA) -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fota_write_obj, 1, 3, fota_write); -#endif - - -static mp_obj_t fota_flush(const mp_obj_t arg0) -{ - int ret = 0; - fota_obj_t *self = MP_OBJ_TO_PTR(arg0); - - ret = Helios_Fota_PackageFlush(self->ctx); - if(ret) - { - MOD_FOTA_LOG("*** fota package flush fail ***\r\n"); - return mp_obj_new_int(-1); - } - MOD_FOTA_LOG("fota package write done, verifing ...\r\n"); - - return mp_obj_new_int(0); -} -#if !defined(PLAT_RDA) -static MP_DEFINE_CONST_FUN_OBJ_1(fota_flush_obj, fota_flush); -#endif -static mp_obj_t fota_verify(const mp_obj_t arg0) -{ - int ret = 0; - fota_obj_t *self = MP_OBJ_TO_PTR(arg0); - MP_THREAD_GIL_EXIT(); - ret = Helios_Fota_PackageVerify(self->ctx); - MP_THREAD_GIL_ENTER(); - - if(ret) - { - MOD_FOTA_LOG("*** fota package verify fail ***\r\n"); - return mp_obj_new_int(-1); - } - MOD_FOTA_LOG("fota package verify done, will restart to update ...\r\n"); - - return mp_obj_new_int(0); -} -#if !defined(PLAT_RDA) -static MP_DEFINE_CONST_FUN_OBJ_1(fota_verify_obj, fota_verify); -#endif -static c_callback_t *fota_callback = NULL; - - -static void mpFotaProgressCB(int sta, int progress) -{ - if(fota_callback != NULL){ - MP_THREAD_GIL_ENTER(); - GC_STACKTOP_SET(); - mp_obj_t fota_list[2] = { - mp_obj_new_int(sta), - mp_obj_new_int(progress), - }; - - mp_sched_schedule_ex(fota_callback, mp_obj_new_list(2, fota_list)); - GC_STACKTOP_CLEAR(); - MP_THREAD_GIL_EXIT(); - } - - if(sta == 1) - { - MOD_FOTA_LOG("fota test downloading (%d)%d ...\r\n", sta, progress); - } - else if(sta == 0) - { - MOD_FOTA_LOG("fota test downloading (%d)%d ...\r\n", sta, progress); - } - else if(sta == 2) - { - MOD_FOTA_LOG("fota test update flag setted, will restart to update ...\r\n"); - #if defined (PLAT_ASR) - Helios_Power_Reset(1); - #endif - } - else if(sta == -1) - { - MOD_FOTA_LOG("fota test download failed (%d)%d\r\n", sta, progress); - MOD_FOTA_LOG("========== fota test end ==========\r\n"); - } -} - -static mp_obj_t fota_get_url() -{ - return mp_obj_new_str(temp_server_address1, strlen(temp_server_address1)); -} -#if defined(PLAT_SONY_ALT1350) -static MP_DEFINE_CONST_FUN_OBJ_0(fota_get_url_obj, fota_get_url); -#endif -static mp_obj_t fota_get_obj() -{ - return MP_OBJ_FROM_PTR(fota_self_obj); -} -#if defined(PLAT_SONY_ALT1350) -static MP_DEFINE_CONST_FUN_OBJ_0(fota_get_obj_obj, fota_get_obj); -#endif - -static mp_obj_t fota_firmware_download(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) -{ - int ret; - char *server_address1 = NULL; - char *server_address2 = NULL; - - enum { - ARG_url1, - ARG_url2, - ARG_callback, - }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_url1, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_url2, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - }; - - mp_arg_val_t args_parse[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args-1, args+1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args_parse); - - if (args_parse[ARG_url1].u_obj != mp_const_none) { - server_address1 = (char *)(mp_obj_str_get_str(args_parse[ARG_url1].u_obj)); - } - - if (args_parse[ARG_url2].u_obj != mp_const_none) { - server_address2 = (char *)(mp_obj_str_get_str(args_parse[ARG_url2].u_obj)); - } - - if (args_parse[ARG_callback].u_obj != mp_const_none) { - static c_callback_t cb = {0}; - memset(&cb, 0, sizeof(c_callback_t)); - fota_callback = &cb; - mp_sched_schedule_callback_register(fota_callback, args_parse[ARG_callback].u_obj); - } - - - MP_THREAD_GIL_EXIT(); - ret = Helios_Fota_firmware_download(server_address1, server_address2, mpFotaProgressCB); - MP_THREAD_GIL_ENTER(); -#if !defined(PLAT_SONY_ALT1350) - if(ret) - { - MOD_FOTA_LOG("*** fota firmware download fail ***\r\n"); - return mp_obj_new_int(-1); - } - return mp_obj_new_int(0); -#else - temp_server_address1 = server_address1; - ret = pyexec_frozen_module("fota_BG950S.py", false); - if(ret == 0) - { - MOD_FOTA_LOG("*** fota execute fail ***\r\n"); - return mp_obj_new_int(-1); - } - return mp_obj_new_int(0); -#endif -} - -static MP_DEFINE_CONST_FUN_OBJ_KW(fota_firmware_download_obj, 1, fota_firmware_download); - -#if defined(PLAT_Qualcomm) -static mp_obj_t fota_download_cancel(const mp_obj_t arg0) -{ - int ret = 0; - - ret = Helios_Fota_Download_Cancel(); - if(ret) - { - MOD_FOTA_LOG("*** fota download cancel fail ***\r\n"); - return mp_obj_new_int(-1); - } - - return mp_obj_new_int(0); -} - -static MP_DEFINE_CONST_FUN_OBJ_1(fota_download_cancel_obj, fota_download_cancel); - -static mp_obj_t fota_apn_set(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) -{ - int ret; - int ip_type = 0; - char *apn = NULL; - char *user = NULL; - char *password = NULL; - - enum { - ARG_ip_type, - ARG_apn, - ARG_user, - ARG_password, - }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_ip_type, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_fota_apn, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_fota_user, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_fota_password, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - }; - - mp_arg_val_t args_parse[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args-1, args+1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args_parse); - - if (args_parse[ARG_ip_type].u_int != -1) - { - ip_type = args_parse[ARG_ip_type].u_int; - } - - if (args_parse[ARG_apn].u_obj != mp_const_none) { - apn = (char *)(mp_obj_str_get_str(args_parse[ARG_apn].u_obj)); - } - - if (args_parse[ARG_user].u_obj != mp_const_none) { - user = (char *)(mp_obj_str_get_str(args_parse[ARG_user].u_obj)); - } - - if (args_parse[ARG_password].u_obj != mp_const_none) { - password = (char *)(mp_obj_str_get_str(args_parse[ARG_password].u_obj)); - } - - ret = Helios_Fota_APN_Set(ip_type, apn, user, password); - - if(ret) - { - return mp_obj_new_int(-1); - } - - return mp_obj_new_int(0); -} - -static MP_DEFINE_CONST_FUN_OBJ_KW(fota_apn_set_obj, 1, fota_apn_set); - -#endif - -static mp_obj_t fota___del__(mp_obj_t self_in) -{ - fota_obj_t *self = MP_OBJ_TO_PTR(self_in); - - Helios_Fota_Deinit(self->ctx); - fota_callback = NULL; - fota_self_obj = NULL; - - return mp_obj_new_int(0); -} -static MP_DEFINE_CONST_FUN_OBJ_1(fota___del___obj, fota___del__); - - -static const mp_rom_map_elem_t fota_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&fota___del___obj) }, - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_fota) }, -#if defined(PLAT_SONY_ALT1350) - { MP_ROM_QSTR(MP_QSTR_fota_get_url), MP_ROM_PTR(&fota_get_url_obj) }, - { MP_ROM_QSTR(MP_QSTR_fota_get_obj), MP_ROM_PTR(&fota_get_obj_obj) }, -#endif -#if !defined(PLAT_RDA) - { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&fota_write_obj) }, - { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&fota_flush_obj) }, - { MP_ROM_QSTR(MP_QSTR_verify), MP_ROM_PTR(&fota_verify_obj) }, -#endif - { MP_ROM_QSTR(MP_QSTR_httpDownload), MP_ROM_PTR(&fota_firmware_download_obj) }, -#if defined(PLAT_Qualcomm) - { MP_ROM_QSTR(MP_QSTR_download_cancel), MP_ROM_PTR(&fota_download_cancel_obj) }, - { MP_ROM_QSTR(MP_QSTR_apn_set), MP_ROM_PTR(&fota_apn_set_obj) }, -#endif -}; -static MP_DEFINE_CONST_DICT(fota_locals_dict, fota_locals_dict_table); - - -MP_DEFINE_CONST_OBJ_TYPE( - mp_fota_type, - MP_QSTR_fota, - MP_TYPE_FLAG_NONE, - make_new, fota_make_new, - locals_dict, &fota_locals_dict - ); -MP_REGISTER_MODULE(MP_QSTR_fota, mp_fota_type); - -#endif /* MICROPY_QPY_MODULE_FOTA */ diff --git a/ports/quectel/modmachine.c b/ports/quectel/modmachine.c deleted file mode 100644 index 2bb59786e980c..0000000000000 --- a/ports/quectel/modmachine.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020-2021 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 "mpconfigport.h" - -#include "py/compile.h" -#include "py/runtime.h" -#include "py/repl.h" -#include "py/mperrno.h" - -#include "modmachine.h" -#include "shared/runtime/pyexec.h" -#include "mphalport.h" - -#if MICROPY_QPY_MODULE_MACHINE -#if MICROPY_PY_SOFT_RESET -static mp_obj_t machine_soft_reset(void) { - pyexec_system_exit = PYEXEC_FORCED_EXIT; - MP_STATE_VM(mp_softreset_exception).traceback_data = NULL; - MP_STATE_MAIN_THREAD(mp_pending_exception) = MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_softreset_exception)); -#if MICROPY_ENABLE_SCHEDULER - if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) { - MP_STATE_VM(sched_state) = MP_SCHED_PENDING; - } -#endif - - mp_mthread_wakeup(); - - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_0(machine_soft_reset_obj, machine_soft_reset); -#endif - - -static const mp_rom_map_elem_t machine_module_globals_table[] = { - { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_machine) }, -#if MICROPY_QPY_MACHINE_PIN - { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) }, -#endif -#if MICROPY_QPY_MACHINE_EXTINT - { MP_ROM_QSTR(MP_QSTR_ExtInt), MP_ROM_PTR(&machine_extint_type) }, -#endif -#if MICROPY_QPY_MACHINE_UART - { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) }, -#endif -#if MICROPY_QPY_MACHINE_SPI - { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_hard_spi_type) }, -#endif -#if MICROPY_QPY_MACHINE_I2C - { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_hard_i2c_type) }, -#endif -#if MICROPY_QPY_MACHINE_I2C_SOFT - { MP_ROM_QSTR(MP_QSTR_I2C_simulation), MP_ROM_PTR(&machine_simulation_i2c_type) }, -#endif -#if MICROPY_QPY_MACHINE_TIMER - { MP_OBJ_NEW_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) }, -#endif -#if MICROPY_PY_SOFT_RESET - { MP_ROM_QSTR(MP_QSTR_SoftReset), MP_ROM_PTR(&machine_soft_reset_obj) }, -#endif -#if MICROPY_QPY_MACHINE_RTC - { MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&machine_rtc_type) }, -#endif -#if MICROPY_QPY_MACHINE_LCD - { MP_ROM_QSTR(MP_QSTR_LCD), MP_ROM_PTR(&machine_lcd_type) }, -#endif -#if MICROPY_QPY_MACHINE_WDT - { MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&machine_wdt_type) }, -#endif -#if MICROPY_QPY_MACHINE_KEYPAD - { MP_ROM_QSTR(MP_QSTR_KeyPad), MP_ROM_PTR(&machine_keypad_type) }, -#endif -#if MICROPY_QPY_MACHINE_NANDFLASH - { MP_ROM_QSTR(MP_QSTR_NANDFLASH), MP_ROM_PTR(&machine_nandflash_type) }, -#endif -}; - -static MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table); - -const mp_obj_module_t mp_module_machine = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t *)&machine_module_globals, -}; - -MP_REGISTER_MODULE(MP_QSTR_machine, mp_module_machine); - -#endif /* MICROPY_QPY_MODULE_MACHINE */ - diff --git a/ports/quectel/modmachine.h b/ports/quectel/modmachine.h deleted file mode 100644 index 31bf023fcbd39..0000000000000 --- a/ports/quectel/modmachine.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020-2021 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 __MOD_MACHINE_H_ -#define __MOD_MACHINE_H_ - -#include "py/obj.h" - -extern const mp_obj_type_t machine_lcd_type; -extern const mp_obj_type_t machine_pin_type; -extern const mp_obj_type_t machine_uart_type; -extern const mp_obj_type_t machine_extint_type; -extern const mp_obj_type_t machine_rtc_type; -extern const mp_obj_type_t machine_timer_type; -extern const mp_obj_type_t machine_hard_i2c_type; -extern const mp_obj_type_t machine_simulation_i2c_type; -extern const mp_obj_type_t machine_hard_spi_type; -extern const mp_obj_type_t machine_wdt_type; -extern const mp_obj_type_t machine_nandflash_type; -#if defined(PLAT_ASR) || defined(PLAT_Unisoc) ||defined(PLAT_ASR_1606) -extern const mp_obj_type_t machine_keypad_type; -#endif - - - -// void machine_timer_deinit_all(void); - -#endif /* __MOD_MACHINE_H_ */ - - diff --git a/ports/quectel/modmisc.c b/ports/quectel/modmisc.c deleted file mode 100644 index 62f88e2bec98d..0000000000000 --- a/ports/quectel/modmisc.c +++ /dev/null @@ -1,253 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020-2021 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 "mpconfigport.h" - -#include "py/compile.h" -#include "py/runtime.h" -#include "py/repl.h" -#include "py/mperrno.h" -#include "py/obj.h" // Pawn 2020-12-19 Add replEnable - -#if MICROPY_QPY_MODULE_MISC - -#include "helios_dev.h" -#include "modmisc.h" - -#if MICROPY_QPY_MISC_PWM -#include "helios_gpio.h" -#endif - -int repl_protect_enable=0; -#if MICROPY_PY_REPL_PASSWORD_PROTECT -extern int repl_protect_password_enable; -extern char g_repl_protect_pswd[64+1]; -#endif - -static mp_obj_t qpy_misc_set_replEnable(size_t n_args, const mp_obj_t *args) -{ - int flag; - - flag = mp_obj_get_int(args[0]); -#if !MICROPY_PY_REPL_PASSWORD_PROTECT - if (flag != 0 && flag != 1) - { - return mp_obj_new_int(-1); - } -#else - if (flag != 0 && flag != 1 && flag != 2) - { - return mp_obj_new_int(-1); - } - - if (flag == 2) { - if (n_args > 1) { - return mp_obj_new_int(-1); - } else { - if ((strlen(g_repl_protect_pswd) > 0) && (repl_protect_enable == 1)) { - return mp_obj_new_int(4); //repl-protection by password - } else if ((strlen(g_repl_protect_pswd) <= 0) && (repl_protect_enable == 1)) { - return mp_obj_new_int(3); //repl refuse - } else if ((strlen(g_repl_protect_pswd) > 0) && (repl_protect_enable == 0)) { - return mp_obj_new_int(2); //repl enable but The password has already been set - } else { - return mp_obj_new_int(1); //repl enable - } - } - } - - mp_buffer_info_t bufinfo = {0}; - if (strlen(g_repl_protect_pswd) > 0) - { - if (n_args > 1) - { - mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); - if ((bufinfo.len > 0) && (strcmp(g_repl_protect_pswd, bufinfo.buf) == 0)) - { - repl_protect_enable = flag; - } - else - { - return mp_obj_new_int(-1); - } - } - else - { - return mp_obj_new_int(-1); - } - } - else -#endif - { - repl_protect_enable = flag; - } - - return mp_obj_new_int(0); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_misc_set_replEnable_obj, 1, 2, qpy_misc_set_replEnable); - -static mp_obj_t qpy_misc_set_repl_password(size_t n_args, const mp_obj_t *args) -{ -#if MICROPY_PY_REPL_PASSWORD_PROTECT - mp_buffer_info_t bufinfo[2] = {0}; - mp_get_buffer_raise(args[0], &bufinfo[0], MP_BUFFER_READ); - - if (strlen(g_repl_protect_pswd) > 0) /*repl-protection by password*/ - { - if (n_args < 2) - return mp_obj_new_int(-1); - - mp_get_buffer_raise(args[1], &bufinfo[1], MP_BUFFER_READ); - if (bufinfo[1].len > 0) - { - if (strcmp(g_repl_protect_pswd, bufinfo[1].buf) == 0) - { - memset(g_repl_protect_pswd, 0, sizeof(g_repl_protect_pswd)); - if (bufinfo[0].len > 0) - { - repl_protect_password_enable = 1; - strncpy(g_repl_protect_pswd, bufinfo[0].buf, bufinfo[0].len); - } - else - { - repl_protect_password_enable = 0; - } - } - else - { - return mp_obj_new_int(-1); - } - } - else - { - return mp_obj_new_int(-1); - } - } - else - { - memset(g_repl_protect_pswd, 0, sizeof(g_repl_protect_pswd)); - if (bufinfo[0].len > 0) - { - repl_protect_password_enable = 1; - strncpy(g_repl_protect_pswd, bufinfo[0].buf, bufinfo[0].len); - } - else - { - repl_protect_password_enable = 0; - } - } - -#endif - return mp_obj_new_int(0); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_misc_set_repl_password_obj, 1, 2, qpy_misc_set_repl_password); - -#if !defined(PLAT_ASR_1803s) -#if defined(PLAT_ASR) -static mp_obj_t qpy_misc_IncCoreVoltage(void) -{ - if(0 != Helios_Dev_IncreaseCoreVoltage()) { - mp_obj_new_int(-1); - } - return mp_obj_new_int(0); -} -static MP_DEFINE_CONST_FUN_OBJ_0(qpy_misc_IncCoreVoltage_obj, qpy_misc_IncCoreVoltage); -#endif - -#endif - -#if MICROPY_QPY_MISC_CFG_NETLIGHT //20220620 add net light nv @jimmy -static mp_obj_t net_light_enable(size_t n_args,const mp_obj_t *args) -{ - int ret = 0; - if(n_args == 1) - { - int value = mp_obj_get_int(args[0]); - if((value == 0) || (value == 1)) - { - ret = Helios_netlight_enable(value); - } - else - { - ret = -1; - } - } - else - { - ret = Helios_netlight_state_get(); - } - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(net_light_enable_obj, 0, 1, net_light_enable); -#endif - -static const mp_rom_map_elem_t misc_module_globals_table[] = { - - { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_misc) }, -#if MICROPY_QPY_MISC_POWER - { MP_ROM_QSTR(MP_QSTR_Power), MP_ROM_PTR(&misc_power_type) }, -#endif -#if MICROPY_QPY_MISC_ADC - { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&misc_adc_type) }, -#endif -#if MICROPY_QPY_MISC_POWERKEY - { MP_ROM_QSTR(MP_QSTR_PowerKey), MP_ROM_PTR(&misc_powerkey_type) }, -#endif -#if MICROPY_QPY_MISC_TEMPERATURE - { MP_ROM_QSTR(MP_QSTR_Temperature), MP_ROM_PTR(&machine_temperature_type) }, -#endif -#if MICROPY_QPY_MISC_PWM - { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&misc_pwm_type) }, - { MP_ROM_QSTR(MP_QSTR_PWM_V2), MP_ROM_PTR(&misc_pwm_v2_type) }, -#endif -#if MICROPY_QPY_MISC_USB - { MP_ROM_QSTR(MP_QSTR_USB), MP_ROM_PTR(&misc_usb_type) }, -#endif -#if MICROPY_QPY_MISC_USBNET - { MP_ROM_QSTR(MP_QSTR_USBNET), MP_ROM_PTR(&misc_usbnet_module) }, -#endif - { MP_ROM_QSTR(MP_QSTR_replEnable), MP_ROM_PTR(&qpy_misc_set_replEnable_obj) }, - { MP_ROM_QSTR(MP_QSTR_replUpdatePassswd), MP_ROM_PTR(&qpy_misc_set_repl_password_obj) }, -#if defined(PLAT_ASR) - { MP_ROM_QSTR(MP_QSTR_IncCoreVoltage), MP_ROM_PTR(&qpy_misc_IncCoreVoltage_obj)}, -#endif -#if MICROPY_QPY_MISC_CFG_NETLIGHT - { MP_ROM_QSTR(MP_QSTR_net_light), MP_ROM_PTR(&net_light_enable_obj) }, -#endif -}; -static MP_DEFINE_CONST_DICT(misc_module_globals, misc_module_globals_table); - -const mp_obj_module_t mp_module_misc = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t *)&misc_module_globals, -}; - -MP_REGISTER_MODULE(MP_QSTR_misc, mp_module_misc); -#endif /* MICROPY_QPY_MODULE_MISC */ - diff --git a/ports/quectel/modmisc.h b/ports/quectel/modmisc.h deleted file mode 100644 index 5c71ad5c217e8..0000000000000 --- a/ports/quectel/modmisc.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020-2021 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 __MOD_MISC_H_ -#define __MOD_MISC_H_ - -#include "py/obj.h" - - -extern const mp_obj_type_t misc_power_type; -extern const mp_obj_type_t misc_pwm_type; -extern const mp_obj_type_t misc_pwm_v2_type; -extern const mp_obj_type_t misc_adc_type; -extern const mp_obj_type_t misc_usb_type; -#if MICROPY_QPY_MISC_USBNET -extern const mp_obj_module_t misc_usbnet_module; -#endif -extern const mp_obj_type_t misc_powerkey_type; - -#if defined(PLAT_RDA) -extern const mp_obj_module_t machine_temperature_type; -#endif - -#endif /* __MOD_MISC_H_ */ - diff --git a/ports/quectel/modnet.c b/ports/quectel/modnet.c deleted file mode 100644 index 167e360f766ef..0000000000000 --- a/ports/quectel/modnet.c +++ /dev/null @@ -1,2423 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020-2021 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 "obj.h" -#include "runtime.h" -#include "mphalport.h" -#include "callbackdeal.h" -#include "gccollect.h" - -#if MICROPY_QPY_MODULE_NET - -#include "helios_debug.h" -#include "helios_nw.h" -#include "helios_dev.h" -#include "helios_sim.h" -#include "helios_datacall.h" -#include "helios_atcmd.h" - -#define QPY_NET_LOG(msg, ...) custom_log(modnet, msg, ##__VA_ARGS__) - -extern int _get_current_simid(void); -/*=============================================================================*/ -/* FUNCTION: qpy_net_set_mode */ -/*=============================================================================*/ -/*!@brief: set network mode - * - * @mode [in] network mode - * @roaming [in] enable or disable roaming - * - * @return: - * 0 - success - * -1 - error - */ -/*=============================================================================*/ -static mp_obj_t qpy_net_set_configuration(size_t n_args, const mp_obj_t *args) -{ - int mode; - int roaming; - int ret = 0; - Helios_NwConfigInfoStruct config_info; - memset(&config_info, 0, sizeof(Helios_NwConfigInfoStruct)); - - mode = mp_obj_get_int(args[0]); - QPY_NET_LOG("[network] set config, mode=%d\r\n", mode); - - int cur_simid = _get_current_simid(); - - if (n_args == 2) - { - roaming = mp_obj_get_int(args[1]); - if((roaming != 0) && (roaming != 1)) - { - QPY_NET_LOG("[network] invalid roaming value, roaming=%d\r\n", roaming); - return mp_obj_new_int(-1); - } - config_info.roaming_switch = roaming; - QPY_NET_LOG("[network] set config, roaming=%d\r\n", roaming); - } - if (n_args ==3) - { - cur_simid = mp_obj_get_int(args[2]); - } - if ((cur_simid != 0) && (cur_simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); - } - config_info.net_mode = mode; - - MP_THREAD_GIL_EXIT(); - ret = Helios_Nw_SetConfiguration(cur_simid, &config_info); - MP_THREAD_GIL_ENTER(); - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_net_set_configuration_obj, 1, 3, qpy_net_set_configuration); - - -/*=============================================================================*/ -/* FUNCTION: qpy_net_get_mode */ -/*=============================================================================*/ -/*!@brief: get network mode - * - * @return: - * returns net mode on success. - * -1 - error - */ -/*=============================================================================*/ -static mp_obj_t qpy_net_get_configuration(size_t n_args, const mp_obj_t *args) -{ - int ret = 0; - Helios_NwConfigInfoStruct config_info; - memset(&config_info, 0, sizeof(Helios_NwConfigInfoStruct)); - - int cur_simid = _get_current_simid(); - if (n_args ==1) - { - cur_simid = mp_obj_get_int(args[0]); - } - if ((cur_simid != 0) && (cur_simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); - } - MP_THREAD_GIL_EXIT(); - ret = Helios_Nw_GetConfiguration(cur_simid, &config_info); - MP_THREAD_GIL_ENTER(); - if(ret == 0) - { - mp_obj_t tuple[2] = {mp_obj_new_int(config_info.net_mode), mp_obj_new_bool(config_info.roaming_switch)}; - return mp_obj_new_tuple(2, tuple); - } - return mp_obj_new_int(-1); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_net_get_configuration_obj, 0, 1, qpy_net_get_configuration); - - -/*=============================================================================*/ -/* FUNCTION: qpy_net_get_csq */ -/*=============================================================================*/ -/*!@brief: get CSQ signal strength - * - * @return: - * returns CSQ on success - * -1 - error - */ -/*=============================================================================*/ -static mp_obj_t qpy_net_get_csq(size_t n_args, const mp_obj_t *args) -{ - int ret = 0; - int csq = -1; - uint8_t status = 0; - int cur_simid = _get_current_simid(); - if (n_args ==1) - { - cur_simid = mp_obj_get_int(args[0]); - } - if ((cur_simid != 0) && (cur_simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); - } - MP_THREAD_GIL_EXIT(); - ret = Helios_SIM_GetCardStatus(cur_simid, (Helios_SIM_Status_e *)&status); - MP_THREAD_GIL_ENTER(); - if (ret == 0) - { - if (status != 1) - { - return mp_obj_new_int(99); - } - } - else - { - return mp_obj_new_int(-1); - } - MP_THREAD_GIL_EXIT(); - csq = Helios_Nw_GetCSQ(cur_simid); - MP_THREAD_GIL_ENTER(); - if(csq != -1) - { - return mp_obj_new_int(csq); - } - - return mp_obj_new_int(-1); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_net_get_csq_obj, 0, 1, qpy_net_get_csq); - -/*=============================================================================*/ -/* FUNCTION: qpy_net_get_nitz_time */ -/*=============================================================================*/ -/*!@brief: get nitz time - * - * @return: - * returns nitz time on success - * -1 - error - */ -/*=============================================================================*/ -static mp_obj_t qpy_net_get_nitz_time(void) -{ - int ret = 0; - Helios_NwNITZTimeInfoStruct info; - memset(&info, 0, sizeof(Helios_NwNITZTimeInfoStruct)); - MP_THREAD_GIL_EXIT(); - ret = Helios_Nw_GetNITZTime(&info); - MP_THREAD_GIL_ENTER(); - if (ret == 0) - { - QPY_NET_LOG("nitz_time:%s\r\n",info.nitz_time); - mp_obj_t tuple[3] = { - mp_obj_new_str(info.nitz_time, strlen(info.nitz_time)), - mp_obj_new_int_from_ull(info.abs_time), - mp_obj_new_int(info.leap_sec)}; - - return mp_obj_new_tuple(3, tuple); - } - - return mp_obj_new_int(-1); -} -static MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_nitz_time_obj, qpy_net_get_nitz_time); - - -/*=============================================================================*/ -/* FUNCTION: qpy_net_get_operator_name */ -/*=============================================================================*/ -/*!@brief: get operator name - * - * @return: - * returns operator name on success - * -1 - error - */ -/*=============================================================================*/ -static mp_obj_t qpy_net_get_operator_name(size_t n_args, const mp_obj_t *args) -{ - int ret = 0; - Helios_NwOperatorInfoStruct info; - Helios_NwRegisterStatusInfoStruct reg_info; - memset(&info, 0, sizeof(Helios_NwOperatorInfoStruct)); - memset(®_info, 0, sizeof(Helios_NwRegisterStatusInfoStruct)); - - int cur_simid = _get_current_simid(); - if (n_args ==1) - { - cur_simid = mp_obj_get_int(args[0]); - } - if ((cur_simid != 0) && (cur_simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); - } - MP_THREAD_GIL_EXIT(); - ret = Helios_Nw_GetRegisterStatus(cur_simid, ®_info); - MP_THREAD_GIL_ENTER(); - - if (ret == 0) - { - if ((reg_info.data_reg.status != 1) && (reg_info.data_reg.status != 5)) - { - QPY_NET_LOG("nw is not registered\r\n"); - return mp_obj_new_int(-1); - } - } - else - { - QPY_NET_LOG("get nw register status failed.\r\n"); - return mp_obj_new_int(-1); - } - - MP_THREAD_GIL_EXIT(); - ret = Helios_Nw_GetOperatorName(cur_simid, &info); - MP_THREAD_GIL_ENTER(); - - if (ret == 0) - { - mp_obj_t tuple[4] = { - mp_obj_new_str(info.long_name, strlen(info.long_name)), - mp_obj_new_str(info.short_name, strlen(info.short_name)), - mp_obj_new_str(info.mcc, strlen(info.mcc)), - mp_obj_new_str(info.mnc, strlen(info.mnc))}; - - return mp_obj_new_tuple(4, tuple); - } - - return mp_obj_new_int(-1); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_net_get_operator_name_obj, 0, 1, qpy_net_get_operator_name); - - -/*=============================================================================*/ -/* FUNCTION: qpy_net_get_selection */ -/*=============================================================================*/ -/*!@brief: get network selection - * - * @return: - * returns (nw_selection,mcc, mnc, act) on success - * -1 - error - */ -/*=============================================================================*/ -static mp_obj_t qpy_net_get_selection(size_t n_args, const mp_obj_t *args) -{ - int ret = 0; - Helios_NwSelectionInfoStruct info; - memset(&info, 0, sizeof(Helios_NwSelectionInfoStruct)); - - int cur_simid = _get_current_simid(); - if (n_args ==1) - { - cur_simid = mp_obj_get_int(args[0]); - } - if ((cur_simid != 0) && (cur_simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); - } - MP_THREAD_GIL_EXIT(); - ret = Helios_Nw_GetSelection(cur_simid, &info); - MP_THREAD_GIL_ENTER(); - if (ret == 0) - { - mp_obj_t tuple[4] = { - mp_obj_new_int(info.nw_selection_mode), - mp_obj_new_str(info.mcc, strlen(info.mcc)), - mp_obj_new_str(info.mnc, strlen(info.mnc)), - mp_obj_new_int(info.act)}; - - return mp_obj_new_tuple(4, tuple); - } - return mp_obj_new_int(-1); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_net_get_selection_obj, 0, 1, qpy_net_get_selection); - - -/*=============================================================================*/ -/* FUNCTION: qpy_net_get_reg_status */ -/*=============================================================================*/ -/*!@brief: get information about network registration - * - * @return: - * returns information about network registration on success - * -1 - error - */ -/*=============================================================================*/ -static mp_obj_t qpy_net_get_reg_status(size_t n_args, const mp_obj_t *args) -{ - int ret = 0; - Helios_NwRegisterStatusInfoStruct info; - memset(&info, 0, sizeof(Helios_NwRegisterStatusInfoStruct)); - - int cur_simid = _get_current_simid(); - if (n_args ==1) - { - cur_simid = mp_obj_get_int(args[0]); - } - if ((cur_simid != 0) && (cur_simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); - } - MP_THREAD_GIL_EXIT(); - ret = Helios_Nw_GetRegisterStatus(cur_simid, &info); - MP_THREAD_GIL_ENTER(); - if (ret == 0) - { - mp_obj_t voice_list[6] = { - mp_obj_new_int(info.voice_reg.status), - mp_obj_new_int(info.voice_reg.lac), - mp_obj_new_int(info.voice_reg.cid), - mp_obj_new_int(info.voice_reg.act), - mp_obj_new_int(info.voice_reg.reject_cause), - mp_obj_new_int(info.voice_reg.psc) - }; - - mp_obj_t data_list[6] = { - mp_obj_new_int(info.data_reg.status), - mp_obj_new_int(info.data_reg.lac), - mp_obj_new_int(info.data_reg.cid), - mp_obj_new_int(info.data_reg.act), - mp_obj_new_int(info.data_reg.reject_cause), - mp_obj_new_int(info.data_reg.psc) - }; - - mp_obj_t tuple[2] = { - mp_obj_new_list(6,voice_list), - mp_obj_new_list(6,data_list)}; - return mp_obj_new_tuple(2, tuple); - } - return mp_obj_new_int(-1); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_net_get_reg_status_obj, 0, 1, qpy_net_get_reg_status); - - -/*=============================================================================*/ -/* FUNCTION: qpy_net_get_signal_strength */ -/*=============================================================================*/ -/*!@brief: get signal strength - * - * @return: - * returns information about signal strength on success - * -1 - error - */ -/*=============================================================================*/ -static mp_obj_t qpy_net_get_signal_strength(size_t n_args, const mp_obj_t *args) -{ - int ret = 0; - Helios_NwSignalStrengthInfoStruct info; - memset(&info, 0, sizeof(Helios_NwSignalStrengthInfoStruct)); - int cur_simid = _get_current_simid(); - if (n_args ==2) - { - cur_simid = mp_obj_get_int(args[1]); - } - if ((cur_simid != 0) && (cur_simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); - } - MP_THREAD_GIL_EXIT(); - ret = Helios_Nw_GetSignalStrength(cur_simid, &info); - MP_THREAD_GIL_ENTER(); - - if (ret == 0) - { - mp_obj_t gw_list[4] = { - mp_obj_new_int(info.gw_signal_strength.rssi), - mp_obj_new_int(info.gw_signal_strength.bit_error_rate), - mp_obj_new_int(info.gw_signal_strength.rscp), - mp_obj_new_int(info.gw_signal_strength.ecno)}; - - #if !defined (PLAT_RDA) //defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_Qualcomm) || defined(PLAT_Unisoc) || defined(PLAT_ASR) - if (n_args > 0) - { - int flag = mp_obj_get_int(args[0]); - if (flag == 1) - { - mp_obj_t lte_list[5] = { - mp_obj_new_int(info.lte_signal_strength.rssi), - mp_obj_new_int(info.lte_signal_strength.rsrp), - mp_obj_new_int(info.lte_signal_strength.rsrq), - mp_obj_new_int(info.lte_signal_strength.cqi), - mp_obj_new_int(info.lte_signal_strength.sinr)}; - - mp_obj_t tuple[2] = { - mp_obj_new_list(4,gw_list), - mp_obj_new_list(5,lte_list)}; - - return mp_obj_new_tuple(2, tuple); - } - } - #endif - mp_obj_t lte_list[4] = { - mp_obj_new_int(info.lte_signal_strength.rssi), - mp_obj_new_int(info.lte_signal_strength.rsrp), - mp_obj_new_int(info.lte_signal_strength.rsrq), - mp_obj_new_int(info.lte_signal_strength.cqi)}; - - mp_obj_t tuple[2] = { - mp_obj_new_list(4,gw_list), - mp_obj_new_list(4,lte_list)}; - - return mp_obj_new_tuple(2, tuple); - } - return mp_obj_new_int(-1); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_net_get_signal_strength_obj, 0, 2, qpy_net_get_signal_strength); - - -/*=============================================================================*/ -/* FUNCTION: qpy_net_get_mnc */ -/*=============================================================================*/ -/*!@brief: get mnc - * - * @return: - * returns mnc on success - * -1 - error - */ -/*=============================================================================*/ -static mp_obj_t qpy_net_get_mnc(size_t n_args, const mp_obj_t *args) -{ - int ret = 0; - int i = 0; - mp_obj_t mnc_list = mp_obj_new_list(0, NULL); - Helios_NwCellInfoStruct info; - memset(&info, 0, sizeof(Helios_NwCellInfoStruct)); - int cur_simid = _get_current_simid(); - if (n_args ==1) - { - cur_simid = mp_obj_get_int(args[0]); - } - if ((cur_simid != 0) && (cur_simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); - } - MP_THREAD_GIL_EXIT(); - ret = Helios_Nw_GetCellInfo(cur_simid, &info); - MP_THREAD_GIL_ENTER(); - - if (ret == 0) - { - if (info.gsm_info_num > 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 3)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, net_type should be in [0,%d]."), HELIOS_BAND_TYPE_MAX_NUM); - } - if ((gsm_band < 0) || (gsm_band > 0x0f)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, gsm_band should be in [0,%x]."), HELIOS_BAND_GSM_MAXVALUE); - } - - size_t len = 0; - mp_obj_t *elem = NULL; - mp_obj_get_array(args[2], &len, &elem); - QPY_NET_LOG("[helios_nw_band]elem num : %d\r\n", len); - if (len != 4) - { - mp_raise_ValueError("invalid value, band tuple should be 4 uint32 elements."); - } - - uint32_t band_hh = mp_obj_get_int_truncated(elem[0]); - uint32_t band_hl = mp_obj_get_int_truncated(elem[1]); - uint32_t band_lh = mp_obj_get_int_truncated(elem[2]); - uint32_t band_ll = mp_obj_get_int_truncated(elem[3]); - QPY_NET_LOG("[helios_nw_band]band_hh=%x, band_hl=%x, band_lh=%x, band_ll=%x\r\n", band_hh, band_hl, band_lh, band_ll); - - Helios_NwBandStruct band_info; - memset(&band_info, 0, sizeof(Helios_NwBandStruct)); - band_info.band_type = net_type; - band_info.band_gsm = gsm_band; - band_info.band_low = (((uint64_t)band_lh) << 32) | band_ll; - band_info.band_hign = (((uint64_t)band_hh) << 32) | band_hl; - QPY_NET_LOG("[helios_nw_band]bandh=%llx, bandl=%llx\r\n", band_info.band_hign, band_info.band_low); - - int cur_simid = _get_current_simid(); - MP_THREAD_GIL_EXIT(); - ret = Helios_Nw_SetBand(cur_simid, &band_info); - MP_THREAD_GIL_ENTER(); - return ((ret == 0) ? mp_obj_new_int(0) : mp_obj_new_int(ret)); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_net_set_band_obj, 3, 3, qpy_net_set_band); - -static mp_obj_t qpy_net_get_band(mp_obj_t net_type) -{ - int band_type = mp_obj_get_int(net_type); - if ((band_type < 0) || (band_type > 3)) - { - mp_raise_ValueError(MP_ERROR_TEXT("invalid value, net_type should be in [0,3].")); - } - - int ret = 0; - Helios_NwBandStruct band_info; - memset(&band_info, 0, sizeof(Helios_NwBandStruct)); - band_info.band_type = band_type; - int cur_simid = _get_current_simid(); - MP_THREAD_GIL_EXIT(); - ret = Helios_Nw_GetBand(cur_simid, &band_info); - MP_THREAD_GIL_ENTER(); - if (ret == 0) - { - char str[64] = {0}; - if (band_type == HELIOS_GSM_BAND) - { - snprintf(str, 64, "0x%x", band_info.band_gsm); - } - else - { - if (band_info.band_hign == 0) - { -#if MICROPY_QPY_MODULE_NET_BAND - uint32_t band_lh = band_info.band_low >> 32; - uint32_t band_ll = band_info.band_low & 0xFFFFFFFF; - QPY_NET_LOG("[helios_nw_band]band_hign=%lx, band_low=%lx\r\n", band_lh, band_ll); - if (band_lh ==0) { - snprintf(str, 64, "0x%lx", band_ll); - } else { - snprintf(str, 64, "0x%lx%08lx", band_lh, band_ll); - } -#else - snprintf(str, 64, "0x%llx", band_info.band_low); -#endif - } - else - { - snprintf(str, 64, "0x%llx%016llx", band_info.band_hign, band_info.band_low); - } - } - return mp_obj_new_str(str, strlen(str)); - } - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_1(qpy_net_get_band_obj, qpy_net_get_band); -#endif - -#if defined(PLAT_ASR) || MICROPY_QPY_MODULE_NET_BAND -static mp_obj_t qpy_net_band_restore(void) -{ - int ret = 0; - int cur_simid = _get_current_simid(); - MP_THREAD_GIL_EXIT(); - ret = Helios_Nw_Band_Restore(cur_simid); - MP_THREAD_GIL_ENTER(); - - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_band_restore_obj, qpy_net_band_restore); -#endif -/*=============================================================================*/ -/* FUNCTION: qpy_net_get_cell_info */ -/*=============================================================================*/ -/*!@brief: get cell informations - * - * @return: - * returns cell informations on success - * -1 - error - */ -/*=============================================================================*/ -static mp_obj_t qpy_net_get_cell_info(size_t n_args, const mp_obj_t *args) -{ - int i = 0; - int ret = 0; - - mp_obj_t list_gsm = mp_obj_new_list(0, NULL); - mp_obj_t list_umts = mp_obj_new_list(0, NULL); - mp_obj_t list_lte = mp_obj_new_list(0, NULL); - Helios_NwCellInfoStruct info; - memset(&info, 0, sizeof(Helios_NwCellInfoStruct)); - - int cur_simid = _get_current_simid(); -#if defined(PLAT_RDA) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) || defined(PLAT_SONY_ALT1350) - int flag_args = -1; -#else - if (n_args ==1) - { - cur_simid = mp_obj_get_int(args[0]); - } - if ((cur_simid != 0) && (cur_simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); - } -#endif - MP_THREAD_GIL_EXIT(); - ret = Helios_Nw_GetCellInfo(cur_simid, &info); - MP_THREAD_GIL_ENTER(); - - if (ret == 0) - { - if (info.gsm_info_num > 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - #if defined(PLAT_RDA) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) || defined(PLAT_SONY_ALT1350) - if (n_args > 0) - { - flag_args = mp_obj_get_int(args[0]); - - if (flag_args == 1) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 1 ) - { - rst = mp_obj_get_int(args[1]); - } - - modem_fun = (uint8_t)mp_obj_get_int(args[0]); - - #if MICROPY_QPY_MODULE_DSDS - int cur_simid = _get_current_simid(); - if (n_args ==3) - { - cur_simid = mp_obj_get_int(args[2]); - } - if ((cur_simid != 0) && (cur_simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); - } - MP_THREAD_GIL_EXIT(); - ret = Helios_Dev_SetModemFunction(modem_fun, rst, cur_simid); - MP_THREAD_GIL_ENTER(); - #else - MP_THREAD_GIL_EXIT(); - ret = Helios_Dev_SetModemFunction(modem_fun, rst,0); - MP_THREAD_GIL_ENTER(); - #endif - if (ret == 0) - { - return mp_obj_new_int(0); - } - - return mp_obj_new_int(-1); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_net_set_modem_fun_obj, 1, 3, qpy_net_set_modem_fun); - -static mp_obj_t qpy_net_set_apn(size_t n_args, const mp_obj_t *args) -{ -#if defined(PLAT_Qualcomm) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || (defined(PLAT_Unisoc) && !defined(BOARD_EG915UEU_AB)) \ - || defined(PLAT_ASR) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_ASR_1602) || defined(PLAT_Unisoc_8910_R06) - if (n_args == 2) - { - mp_buffer_info_t apninfo = {0}; - mp_get_buffer_raise(args[0], &apninfo, MP_BUFFER_READ); - uint8_t net_simid = mp_obj_get_int(args[1]); - int ret = 0; - if (net_simid != 0) - { - mp_raise_ValueError(MP_ERROR_TEXT("invalid simid.")); - } - if (apninfo.len > HELIOS_APN_LEN_MAX) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, the length of apn should be no more than [%d] bytes."), HELIOS_APN_LEN_MAX); - } - MP_THREAD_GIL_EXIT(); - ret = Helios_Nw_SetApn((char *)apninfo.buf, net_simid); - MP_THREAD_GIL_ENTER(); - if (ret == 0) - { - return mp_obj_new_int(0); - } - return mp_obj_new_int(-1); - } - else -#endif - { - if (n_args == 7)//pid/iptype/apn/usrname/pwd/authtype/simid - { - int8_t ret = 0; - uint8_t net_simid = mp_obj_get_int(args[6]); - uint8_t profile_id = mp_obj_get_int(args[0]); - int ip_type = mp_obj_get_int(args[1]); - int auth_type = mp_obj_get_int(args[5]); - - mp_buffer_info_t apninfo = {0}; - mp_buffer_info_t usrinfo = {0}; - mp_buffer_info_t pwdinfo = {0}; - mp_get_buffer_raise(args[2], &apninfo, MP_BUFFER_READ); - mp_get_buffer_raise(args[3], &usrinfo, MP_BUFFER_READ); - mp_get_buffer_raise(args[4], &pwdinfo, MP_BUFFER_READ); - - int min_profile_id = (int)HELIOS_PROFILE_IDX_MIN; - int max_profile_id = (int)HELIOS_PROFILE_IDX_MAX; - - #if MICROPY_QPY_MODULE_DSDS - if ((net_simid != 0) && (net_simid != 1)) - #else - if (net_simid != 0) - #endif - { - mp_raise_ValueError(MP_ERROR_TEXT("invalid simid.")); - } - if ((profile_id < min_profile_id) || (profile_id > max_profile_id)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, profileIdx should be in [%d,%d]."), min_profile_id, max_profile_id); - } - if ((ip_type < 0) || (ip_type > HELIOS_PDP_TYPE_NUM - 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, ipType should be in [0~%d]."), HELIOS_PDP_TYPE_NUM-1); - } - if ((auth_type < 0) || (auth_type > HELIOS_AUTH_TYPE_NUM - 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, authType should be in [0~%d]."), HELIOS_AUTH_TYPE_NUM-1); - } - if (apninfo.len > HELIOS_APN_LEN_MAX) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, the length of apn should be no more than [%d] bytes."), HELIOS_APN_LEN_MAX); - } - if (usrinfo.len > HELIOS_USR_LEN_MAX) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, the length of username should be no more than [%d] bytes."), HELIOS_USR_LEN_MAX); - } - if (pwdinfo.len > HELIOS_PWD_LEN_MAX) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, the length of password should be no more than [%d] bytes."), HELIOS_PWD_LEN_MAX); - } - - QPY_NET_LOG("[NW-PDNINFO] profile_idx=%d, ip_version=%d, auth_type=%d\r\n", profile_id, ip_type, auth_type); - QPY_NET_LOG("[NW-PDNINFO] anp_name=%s, usr_name=%s, password=%s\r\n", apninfo.buf, usrinfo.buf, pwdinfo.buf); - - Helios_DataCallStartStruct pdpinfo_set; - memset(&pdpinfo_set, 0, sizeof(Helios_DataCallStartStruct)); - - pdpinfo_set.ip_type = (int32_t)ip_type; - pdpinfo_set.auth = (int32_t)auth_type; - snprintf(pdpinfo_set.apn, sizeof(pdpinfo_set.apn), "%s", (char *)apninfo.buf); - snprintf(pdpinfo_set.user, sizeof(pdpinfo_set.user), "%s", (char *)usrinfo.buf); - snprintf(pdpinfo_set.pwd, sizeof(pdpinfo_set.pwd), "%s", (char *)pwdinfo.buf); - MP_THREAD_GIL_EXIT(); - #if MICROPY_QPY_MODULE_DSDS - ret = Helios_DataCall_SetPDPContext(net_simid, profile_id, &pdpinfo_set); - #else - ret = Helios_DataCall_SetPDPContext(profile_id, &pdpinfo_set); - #endif - MP_THREAD_GIL_ENTER(); - return mp_obj_new_int(ret); - } - else - { - mp_raise_ValueError(MP_ERROR_TEXT("Incorrect parameter number!")); - } - } -} - -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_net_set_apn_obj, 2, 7, qpy_net_set_apn); - -static mp_obj_t qpy_net_get_apn(size_t n_args, const mp_obj_t *args) -{ -#if defined(PLAT_Qualcomm) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || (defined(PLAT_Unisoc) && !defined(BOARD_EG915UEU_AB)) \ - || defined(PLAT_ASR) || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_ASR_1602) || defined(PLAT_Unisoc_8910_R06) - if (n_args == 1) - { - uint8_t net_simid = mp_obj_get_int(args[0]); - int ret = 0; - char apn[99+1] = {0}; - if (net_simid != 0) - { - mp_raise_ValueError(MP_ERROR_TEXT("invalid simid.")); - } - MP_THREAD_GIL_EXIT(); - ret = Helios_Nw_GetApn(apn, net_simid); - MP_THREAD_GIL_ENTER(); - if (ret == 0) - { - return mp_obj_new_str(apn, strlen(apn)); - } - return mp_obj_new_int(-1); - } - else -#endif - { - if (n_args == 2) //pid/simid - { - uint8_t net_simid = mp_obj_get_int(args[1]); - int ret = 0; - uint8_t profile_id = mp_obj_get_int(args[0]); - Helios_DataCallStartStruct pdpinfo_get; - - #if MICROPY_QPY_MODULE_DSDS - if ((net_simid != 0) && (net_simid != 1)) - #else - if (net_simid != 0) - #endif - { - mp_raise_ValueError(MP_ERROR_TEXT("invalid simid.")); - } - - if ((profile_id < HELIOS_PROFILE_IDX_MIN) || (profile_id > HELIOS_PROFILE_IDX_MAX)) - { - mp_raise_ValueError(MP_ERROR_TEXT("invalid profile_id.")); - } - memset(&pdpinfo_get, 0, sizeof(Helios_DataCallStartStruct)); - MP_THREAD_GIL_EXIT(); - #if MICROPY_QPY_MODULE_DSDS - ret = Helios_DataCall_GetPDPContext(net_simid,profile_id, &pdpinfo_get); - #else - ret = Helios_DataCall_GetPDPContext(profile_id, &pdpinfo_get); - #endif - MP_THREAD_GIL_ENTER(); - if (ret != 0) - return mp_obj_new_int(-1); - - mp_obj_t tuple[5] = { - mp_obj_new_int(pdpinfo_get.ip_type), - mp_obj_new_str(pdpinfo_get.apn, strlen(pdpinfo_get.apn)), - mp_obj_new_str(pdpinfo_get.user, strlen(pdpinfo_get.user)), - mp_obj_new_str(pdpinfo_get.pwd, strlen(pdpinfo_get.pwd)), - mp_obj_new_int(pdpinfo_get.auth)}; - - return mp_obj_new_tuple(5, tuple); - } - else - { - mp_raise_ValueError(MP_ERROR_TEXT("Incorrect parameter number!")); - } - } -} - -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_net_get_apn_obj, 1, 2, qpy_net_get_apn); - -#if MICROPY_QPY_MODULE_NET_LED -static mp_obj_t qpy_set_networkled_config( const mp_obj_t args) -{ - - typedef struct network_led_control_info{ - int i_gpio_num; // GPIO_NO - uint32_t i_net_type; // TCP UDP 0-tcp 1-udp - uint32_t i_gpio_low_time; // GPIO LOW times ms - uint32_t i_gpio_hight_time; // GPIO hight times ms - uint32_t i_loop_nums; // cycle nums - }network_led_control_info_t; - - int Helios_NW_Led_Config(network_led_control_info_t config); - volatile network_led_control_info_t config; - mp_obj_t *items = NULL; - size_t len = 0; - char *str = NULL; - mp_obj_list_get(args, &len, &items); - if ( len!= 5){ - return mp_obj_new_int(-1); - } - config.i_gpio_num = (int)mp_obj_get_int(items[0]); - config.i_net_type = (int)mp_obj_get_int(items[1]); - config.i_gpio_low_time =(int) mp_obj_get_int(items[2]); - config.i_gpio_hight_time = (int)mp_obj_get_int(items[3]); - config.i_loop_nums =(int) mp_obj_get_int(items[4]); - MP_THREAD_GIL_EXIT(); - Helios_NW_Led_Config(config); - MP_THREAD_GIL_ENTER(); - return mp_obj_new_int(0); - -} -static MP_DEFINE_CONST_FUN_OBJ_1(qpy_set_networkled_config_obj, qpy_set_networkled_config); -#endif - -static c_callback_t *g_net_user_callback = NULL; - -static void qpy_net_event_handler(uint8_t sim_id, int32_t event_id, void *ctx) -{ - switch (event_id) - { - case HELIOS_NW_DATA_REG_STATUS_IND: - { - Helios_NwRegisterInfoStruct *nw_register_status = (Helios_NwRegisterInfoStruct *)ctx; - - if (g_net_user_callback) - { - QPY_NET_LOG("[net] callback start.\r\n"); - st_CallBack_Net *Net_param = malloc(sizeof(st_CallBack_Net)); - if(NULL != Net_param) - { - Net_param->event_id = event_id; - Net_param->status = nw_register_status->status; - Net_param->lac = nw_register_status->lac; - Net_param->cid = nw_register_status->cid; - Net_param->act = nw_register_status->act; - Net_param->callback = *g_net_user_callback; - QPY_NET_LOG("[net] callback start 1.\r\n"); - qpy_send_msg_to_callback_deal_thread(CALLBACK_TYPE_ID_NET, Net_param); - } - QPY_NET_LOG("[net] callback end.\r\n"); - } - break; - } - #if MICROPY_QPY_MODULE_JAMDET - case HELIOS_NW_JAMMING_DETECT_IND: - { - /* ... */ - QPY_NET_LOG("[net]jamming event.\r\n", event_id); - uint8_t jam_status = *(uint8_t *)ctx; - if (g_net_user_callback) - { - MP_THREAD_GIL_ENTER(); - GC_STACKTOP_SET(); - mp_obj_t tuple[3] = - { - mp_obj_new_int(event_id), - mp_obj_new_int(jam_status), - mp_obj_new_int(sim_id) - }; - mp_sched_schedule_ex(g_net_user_callback, mp_obj_new_tuple(3, tuple)); - GC_STACKTOP_CLEAR(); - MP_THREAD_GIL_EXIT(); - } - break; - } - #endif - case HELIOS_NW_VOICE_REG_STATUS_IND: - /* ... */ - QPY_NET_LOG("[net] ind_flag = %x\r\n", event_id); - break; - case HELIOS_NW_NITZ_TIME_UPDATE_IND: - /* ... */ - QPY_NET_LOG("[net] ind_flag = %x\r\n", event_id); - break; - case HELIOS_NW_SIGNAL_QUALITY_IND: - /* ... */ - QPY_NET_LOG("[net] ind_flag = %x\r\n", event_id); - break; - default: - QPY_NET_LOG("[net] event handler, ind=%x\r\n", event_id); - break; - } -} - -/*=============================================================================*/ -/* FUNCTION: qpy_net_add_event_handler */ -/*=============================================================================*/ -/*!@brief: registered user callback function - * - * @handler [in] callback function - * - * @return: - * 0 - success - * -1 - error - */ -/*=============================================================================*/ -static mp_obj_t qpy_net_add_event_handler(mp_obj_t handler) -{ - static c_callback_t cb = {0}; - memset(&cb, 0, sizeof(c_callback_t)); - cb.arg = mp_obj_new_tuple(5, NULL); - g_net_user_callback = &cb; - mp_sched_schedule_callback_register(g_net_user_callback, handler); - Helios_NwInitStruct info; - memset(&info, 0, sizeof(Helios_NwInitStruct)); - - info.user_cb = qpy_net_event_handler; - Helios_Nw_Init(&info); - return mp_obj_new_int(0); -} -static MP_DEFINE_CONST_FUN_OBJ_1(qpy_net_add_event_handler_obj, qpy_net_add_event_handler); - -/*=============================================================================*/ -/* FUNCTION: qpy_module_net_deinit */ -/*=============================================================================*/ -/*!@brief: deinit net module - * - * - * @return: - * 0 - success - */ -/*=============================================================================*/ -static mp_obj_t qpy_module_net_deinit(void) -{ - QPY_NET_LOG("module net deinit.\r\n"); -#if defined(PLAT_ASR) || defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_Unisoc_8910_R06) - MP_THREAD_GIL_EXIT(); - Helios_Nw_Deinit(); - MP_THREAD_GIL_ENTER(); -#endif - g_net_user_callback = NULL; - return mp_obj_new_int(0); -} -static MP_DEFINE_CONST_FUN_OBJ_0(qpy_module_net_deinit_obj, qpy_module_net_deinit); - -#if MICROPY_QPY_MODULE_FTM_MODE -#include "helios_ftm.h" -#include "helios_os.h" -static mp_obj_t qpy_ftm_mode_switch(mp_obj_t mode) -{ - int ret = -1; - uint8_t ftm_mode = (uint8_t)mp_obj_get_int(mode); - if(ftm_mode > 1) return mp_obj_new_int(-1); - - MP_THREAD_GIL_EXIT(); - if(ftm_mode) - { - ret = Helios_Dev_SetModemFunction(!ftm_mode, 0, 0); - Helios_sleep(1); - ret = (!ret) ? helios_ftm_mode_switch(ftm_mode) : -1; - } - else - { - ret = helios_ftm_mode_switch(ftm_mode); - Helios_sleep(1); - ret = (!ret) ? Helios_Dev_SetModemFunction(!ftm_mode, 0, 0) : -1; - } - MP_THREAD_GIL_ENTER(); - - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_1(qpy_ftm_mode_switch_obj, qpy_ftm_mode_switch); - -static mp_obj_t qpy_ftm_mode_start(mp_obj_t band, mp_obj_t channel, mp_obj_t power) -{ - int ret = -1; - - MP_THREAD_GIL_EXIT(); - ret = helios_ftm_test_start((uint16_t)mp_obj_get_int(band), (uint32_t)mp_obj_get_int(channel), (uint8_t)mp_obj_get_int(power)); - MP_THREAD_GIL_ENTER(); - - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_3(qpy_ftm_mode_start_obj, qpy_ftm_mode_start); - -static mp_obj_t qpy_ftm_mode_stop(void) -{ - int ret = -1; - MP_THREAD_GIL_EXIT(); - //uint16_t band, uint32_t tx_channel,uint8_t tx_power - ret = helios_ftm_test_stop(); - MP_THREAD_GIL_ENTER(); - - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_0(qpy_ftm_mode_stop_obj, qpy_ftm_mode_stop); -#endif - - - -#if MICROPY_QPY_MODULE_BACKCELL - -static mp_obj_t qpy_add_black_cell(size_t n_args, const mp_obj_t *args) -{ - int8_t ret = -1; - uint8_t rat =5; - if (n_args == 2){ - rat = mp_obj_get_int(args[1]); - } - mp_buffer_info_t cell_info = {0}; - mp_get_buffer_raise(args[0], &cell_info, MP_BUFFER_READ); - MP_THREAD_GIL_EXIT(); - ret = Helios_Nw_AddBlackCell(rat, (char *)cell_info.buf); - MP_THREAD_GIL_ENTER(); - if (ret != 0){ - ret =-1; - } - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_add_black_cell_obj, 1, 2, qpy_add_black_cell); - -static mp_obj_t qpy_get_black_cell(void) -{ - int8_t ret = 0; - int8_t i = 0; - mp_obj_t list_gsm = mp_obj_new_list(0, NULL); - mp_obj_t list_lte = mp_obj_new_list(0, NULL); - Helios_NwBackCellInfo info; - memset(&info, 0, sizeof(Helios_NwBackCellInfo)); - MP_THREAD_GIL_EXIT(); - ret = Helios_Nw_GetBlackCell(&info); - MP_THREAD_GIL_ENTER(); - if (ret == 0){ - if (info.gsm_info_num > 0) - { - for (i=0; i 0) - { - for (i=0; i 1) - { - mp_raise_ValueError(MP_ERROR_TEXT("invalid value, blackcellCfg should be in [0,1].")); - } - uint8_t blackcellCfg_num = mp_obj_get_int(args[1]); - if (blackcellCfg_num == 0 || blackcellCfg_num > 8) - { - mp_raise_ValueError(MP_ERROR_TEXT("invalid value, blackcellCfg_num should be in [1,8].")); - } - MP_THREAD_GIL_EXIT(); - ret = Helios_Nw_SetBlackCellCfg(blackcellCfg, blackcellCfg_num); - MP_THREAD_GIL_ENTER(); - if (ret != 0){ - ret =-1; - } - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_set_black_cell_cfg_obj, 2, 2, qpy_set_black_cell_cfg); - -static mp_obj_t qpy_delete_black_cell(size_t n_args, const mp_obj_t *args) -{ - int8_t ret = -1; - if (n_args == 0) - { - ret = Helios_Nw_DeleteAllBlackCell(); - } - else if (n_args == 1) - { - uint8_t rat = 5; - mp_buffer_info_t cell_info = {0}; - mp_get_buffer_raise(args[0], &cell_info, MP_BUFFER_READ); - MP_THREAD_GIL_EXIT(); - ret = Helios_Nw_DeleteBlackCell(rat, (char *)cell_info.buf); - MP_THREAD_GIL_ENTER(); - } - if (ret != 0){ - ret =-1; - } - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_delete_black_cell_obj, 0, 1, qpy_delete_black_cell); -#endif - - -#if MICROPY_QPY_MODULE_DRX_TIMER -static mp_obj_t qpy_net_get_drxtm(void) -{ - uint8_t cur_simid = _get_current_simid(); - uint16_t drx_timer_value = 0; - MP_THREAD_GIL_EXIT(); - if(0 != Helios_Nw_GetDrxtm(cur_simid, &drx_timer_value)) { - MP_THREAD_GIL_ENTER(); - return mp_obj_new_int(-1); - } - MP_THREAD_GIL_ENTER(); - return mp_obj_new_int(drx_timer_value); -} -static MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_drxtm_obj, qpy_net_get_drxtm); - -static mp_obj_t qpy_net_set_drxtm(mp_obj_t drx_timer) -{ - uint8_t cur_simid = _get_current_simid(); - uint16_t drx_timer_value = (uint16_t)mp_obj_get_int(drx_timer); - MP_THREAD_GIL_EXIT(); - if(0 != Helios_Nw_SetDrxtm(cur_simid, drx_timer_value)) { - MP_THREAD_GIL_ENTER(); - return mp_obj_new_int(-1); - } - MP_THREAD_GIL_ENTER(); - return mp_obj_new_int(0); -} -static MP_DEFINE_CONST_FUN_OBJ_1(qpy_net_set_drxtm_obj, qpy_net_set_drxtm); -#endif - -#if MICROPY_QPY_MODULE_JAMDET -static mp_obj_t qpy_jamdet_set_switch(size_t n_args, const mp_obj_t *args) -{ - uint8_t sim_id = 0; - - uint8_t opt = (uint8_t)mp_obj_get_int(args[0]); - if ((opt != 0) && (opt != 1)) - { - mp_raise_ValueError("invalid value, opt shuould be 0 or 1,"); - } - - if (n_args == 2) - { - sim_id = (uint8_t)mp_obj_get_int(args[1]); - if ((sim_id != 0) && (sim_id != 1)) - { - mp_raise_ValueError("invalid value, simId should be 0 or 1."); - } - } - - MP_THREAD_GIL_EXIT(); - int ret = Helios_Nw_SetJamdetSwitch(sim_id, opt); - MP_THREAD_GIL_ENTER(); - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_jamdet_set_switch_obj, 1, 2, qpy_jamdet_set_switch); - -static mp_obj_t qpy_jamdet_get_switch(size_t n_args, const mp_obj_t *args) -{ - uint8_t sim_id = 0; - if (n_args == 1) - { - sim_id = (uint8_t)mp_obj_get_int(args[0]); - if ((sim_id != 0) && (sim_id != 1)) - { - mp_raise_ValueError("invalid value, simId should be 0 or 1."); - } - } - uint8_t opt = 0; - MP_THREAD_GIL_EXIT(); - Helios_Nw_GetJamdetSwitch(sim_id, &opt); - MP_THREAD_GIL_ENTER(); - - return mp_obj_new_int(opt); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_jamdet_get_switch_obj, 0, 1, qpy_jamdet_get_switch); - -static mp_obj_t qpy_jamdet_set_configuration(size_t n_args, const mp_obj_t *args) -{ - uint8_t sim_id = 0; - if (n_args == 8) - { - sim_id = (uint8_t)mp_obj_get_int(args[7]); - if ((sim_id != 0) && (sim_id != 1)) - { - mp_raise_ValueError("invalid value, simId should be 0 or 1."); - } - } - - Helios_NwJamDetConfigStruct cfg = {0}; - cfg.gsm_minch = mp_obj_get_int(args[0]); - cfg.gsm_sinr = mp_obj_get_int(args[1]); - cfg.gsm_rssi = mp_obj_get_int(args[2]); - cfg.lte_rsrp = mp_obj_get_int(args[3]); - cfg.lte_rsrq = mp_obj_get_int(args[4]); - cfg.lte_rssi = mp_obj_get_int(args[5]); - cfg.shake_period = mp_obj_get_int(args[6]); - - if ((cfg.gsm_minch < 0) || (cfg.gsm_minch > 254)) - { - mp_raise_ValueError("invalid value, gsm_minch should be in [0,254]."); - } - if ((cfg.gsm_sinr < 0) || (cfg.gsm_sinr > 63)) - { - mp_raise_ValueError("invalid value, gsm_sinr should be in [0,63]."); - } - if ((cfg.gsm_rssi < -110) || (cfg.gsm_rssi > -50)) - { - mp_raise_ValueError("invalid value, gsm_rssi should be in [-110,-50]."); - } - if ((cfg.lte_rsrp < -140) || (cfg.lte_rsrp > -44)) - { - mp_raise_ValueError("invalid value, lte_rsrp should be in [-140,-44]."); - } - if ((cfg.lte_rsrq < -19) || (cfg.lte_rsrq > -3)) - { - mp_raise_ValueError("invalid value, lte_rsrq should be in [-19,-3]."); - } - if ((cfg.lte_rssi < -120) || (cfg.lte_rssi > -20)) - { - mp_raise_ValueError("invalid value, lte_rssi should be in [-120,-20]."); - } - if ((cfg.shake_period < 1) || (cfg.shake_period > 10)) - { - mp_raise_ValueError("invalid value, shake_period should be in [1,10]."); - } - - MP_THREAD_GIL_EXIT(); - int ret = Helios_Nw_SetJamdetConfiguration(sim_id, &cfg); - MP_THREAD_GIL_ENTER(); - - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_jamdet_set_config_obj, 7, 8, qpy_jamdet_set_configuration); - -static mp_obj_t qpy_jamdet_get_configuration(size_t n_args, const mp_obj_t *args) -{ - uint8_t sim_id = 0; - if (n_args == 1) - { - sim_id = (uint8_t)mp_obj_get_int(args[0]); - if ((sim_id != 0) && (sim_id != 1)) - { - mp_raise_ValueError("invalid value, simId should be 0 or 1."); - } - } - - Helios_NwJamDetConfigStruct cfg = {0}; - MP_THREAD_GIL_EXIT(); - Helios_Nw_GetJamdetConfiguration(sim_id, &cfg); - MP_THREAD_GIL_ENTER(); - mp_obj_t info[7] = - { - mp_obj_new_int(cfg.gsm_minch), - mp_obj_new_int(cfg.gsm_sinr), - mp_obj_new_int(cfg.gsm_rssi), - mp_obj_new_int(cfg.lte_rsrp), - mp_obj_new_int(cfg.lte_rsrq), - mp_obj_new_int(cfg.lte_rssi), - mp_obj_new_int(cfg.shake_period) - }; - return mp_obj_new_tuple(7, info); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_jamdet_get_config_obj, 0, 1, qpy_jamdet_get_configuration); - -static mp_obj_t qpy_jamdet_get_stauts(size_t n_args, const mp_obj_t *args) -{ - uint8_t sim_id = 0; - if (n_args == 1) - { - sim_id = (uint8_t)mp_obj_get_int(args[0]); - if ((sim_id != 0) && (sim_id != 1)) - { - mp_raise_ValueError("invalid value, simId should be 0 or 1."); - } - } - - uint8_t opt = 0; - MP_THREAD_GIL_EXIT(); - Helios_Nw_GetJamdetSwitch(sim_id, &opt); - MP_THREAD_GIL_ENTER(); - if (opt == 0) - { - mp_raise_ValueError("Please enable the jamdet function first."); - } - - uint8_t status = 0; - MP_THREAD_GIL_EXIT(); - int ret = Helios_Nw_GetJamdetStatus(sim_id, &status); - MP_THREAD_GIL_ENTER(); - if (ret == 0) - { - return mp_obj_new_int(status); - } - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_jamdet_get_stauts_obj, 0, 1, qpy_jamdet_get_stauts); - -#endif - -#if defined(MICROPY_QPY_MODULE_IMS_STATUS) -static mp_obj_t qpy_net_get_ims_register(size_t n_args, const mp_obj_t *args) -{ - uint8_t sim_id = _get_current_simid();; - if (n_args == 1) { - sim_id = mp_obj_get_int(args[0]); - } - if ((sim_id != 0) && (sim_id != 1)) - { - mp_raise_ValueError("invalid value, simId should be 0 or 1."); - } - MP_THREAD_GIL_EXIT(); - int ret = Helios_Nw_ImsIsRegister(sim_id); - MP_THREAD_GIL_ENTER(); - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_net_get_ims_register_obj, 0, 1, qpy_net_get_ims_register); -#endif - -#if MICROPY_QPY_MODULE_NET_EX - -static mp_obj_t qpy_net_get_T3402(void) -{ - char resp[128] = {0}; - char para[64] = {0}; - MP_THREAD_GIL_EXIT(); - HELIOS_AT_RESP_STATUS_E ret = Helios_Atcmd_Send_Sync(0, "AT+QCFG=\"emmtimer\"\r\n", resp, sizeof(resp), NULL, 10); - MP_THREAD_GIL_ENTER(); - if(ret == HELIOS_AT_RESP_OK) { - Helios_Atcmd_Get_Para_Value_Str(resp, 1, 1, para, sizeof(para)); - if(strlen(para) != 0) { - return mp_obj_new_str(para, strlen(para)); - } - } - return mp_obj_new_int(-1); -} -static MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_T3402_obj, qpy_net_get_T3402); - - -static mp_obj_t qpy_net_get_T3412(void) -{ - char resp[128] = {0}; - char para[64] = {0}; - MP_THREAD_GIL_EXIT(); - HELIOS_AT_RESP_STATUS_E ret = Helios_Atcmd_Send_Sync(0, "AT+QCFG=\"emmtimer\"\r\n", resp, sizeof(resp), NULL, 10); - MP_THREAD_GIL_ENTER(); - if(ret == HELIOS_AT_RESP_OK) { - Helios_Atcmd_Get_Para_Value_Str(resp, 1, 2, para, sizeof(para)); - if(strlen(para) != 0) { - return mp_obj_new_str(para, strlen(para)); - } - } - return mp_obj_new_int(-1); -} -static MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_T3412_obj, qpy_net_get_T3412); - - -static mp_obj_t qpy_net_get_T3324(void) -{ - char resp[128] = {0}; - char para[64] = {0}; - char cmd[64] = {0}; - int n = 0; - HELIOS_AT_RESP_STATUS_E ret = HELIOS_AT_RESP_OK; - MP_THREAD_GIL_EXIT(); - ret = Helios_Atcmd_Send_Sync(0, "AT+CEREG?\r\n", resp, sizeof(resp), NULL, 10); - MP_THREAD_GIL_ENTER(); - if(ret != HELIOS_AT_RESP_OK) { - return mp_obj_new_int(-1); - } - Helios_Atcmd_Get_Para_Value_Str(resp, 1, 0, para, sizeof(para)); - if(strlen(para) != 0) { - n = atoi(para); - } - memset(resp, 0 ,sizeof(resp)); - memset(para, 0 ,sizeof(para)); - if (n !=4) { - MP_THREAD_GIL_EXIT(); - ret = Helios_Atcmd_Send_Sync(0, "AT+CEREG=4\r\n", NULL, 0, NULL, 10); - MP_THREAD_GIL_ENTER(); - if(ret != HELIOS_AT_RESP_OK) { - return mp_obj_new_int(-1); - } - }else { - Helios_Atcmd_Get_Para_Value_Str(resp, 1, 7, para, sizeof(para)); - if(strlen(para) != 0) { - return mp_obj_new_str(para, strlen(para)); - } - } - MP_THREAD_GIL_EXIT(); - Helios_Atcmd_Send_Sync(0, "AT+CEREG?\r\n", resp, sizeof(resp), NULL, 10); - MP_THREAD_GIL_ENTER(); - Helios_Atcmd_Get_Para_Value_Str(resp, 1, 7, para, sizeof(para)); - snprintf(cmd, 64, "AT+CEREG=%d\r\n", n); - MP_THREAD_GIL_EXIT(); - ret = Helios_Atcmd_Send_Sync(0, cmd, NULL, 0, NULL, 10); - MP_THREAD_GIL_ENTER(); - if(ret != HELIOS_AT_RESP_OK) { - return mp_obj_new_int(-1); - } - return mp_obj_new_str(para, strlen(para)); - -} -static MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_T3324_obj, qpy_net_get_T3324); - - -static mp_obj_t qpy_net_get_TeDRX(void) -{ - char resp[128] = {0}; - char para[64] = {0}; - MP_THREAD_GIL_EXIT(); - HELIOS_AT_RESP_STATUS_E ret = Helios_Atcmd_Send_Sync(0, "AT+CEDRXRDP\r\n", resp, sizeof(resp), NULL, 10); - MP_THREAD_GIL_ENTER(); - if(ret == HELIOS_AT_RESP_OK) { - Helios_Atcmd_Get_Para_Value_Str(resp, 1, 1, para, sizeof(para)); - return mp_obj_new_str(para, strlen(para)); - } - return mp_obj_new_int(-1); -} -static MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_TeDRX_obj, qpy_net_get_TeDRX); - -static mp_obj_t qpy_net_get_TPTW(void) -{ - char resp[128] = {0}; - char para[64] = {0}; - MP_THREAD_GIL_EXIT(); - HELIOS_AT_RESP_STATUS_E ret = Helios_Atcmd_Send_Sync(0, "AT+CEDRXRDP\r\n", resp, sizeof(resp), NULL, 10); - MP_THREAD_GIL_ENTER(); - if(ret == HELIOS_AT_RESP_OK) { - Helios_Atcmd_Get_Para_Value_Str(resp, 1, 3, para, sizeof(para)); - return mp_obj_new_str(para, strlen(para)); - } - return mp_obj_new_int(-1); -} -static MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_TPTW_obj, qpy_net_get_TPTW); - -static mp_obj_t qpy_net_get_qRxlevMin(void) -{ - char resp[256] = {0}; - char para[64] = {0}; - MP_THREAD_GIL_EXIT(); - HELIOS_AT_RESP_STATUS_E ret = Helios_Atcmd_Send_Sync(0, "AT+QCFG=\"sibinfo\"\r\n", resp, sizeof(resp), NULL, 10); - MP_THREAD_GIL_ENTER(); - if(ret == HELIOS_AT_RESP_OK) { - Helios_Atcmd_Get_Para_Value_Str(resp, 1, 3, para, sizeof(para)); - if(strlen(para) != 0) { - return mp_obj_new_str(para, strlen(para)); - } - } - return mp_obj_new_int(-1); -} -static MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_qRxlevMin_obj, qpy_net_get_qRxlevMin); - -static mp_obj_t qpy_net_get_reject_cause(void) -{ - char resp[128] = {0}; - char para[64] = {0}; - MP_THREAD_GIL_EXIT(); - HELIOS_AT_RESP_STATUS_E ret = Helios_Atcmd_Send_Sync(0, "AT+QCFG=\"emmcause\"\r\n", resp, sizeof(resp), NULL, 10); - MP_THREAD_GIL_ENTER(); - if(ret == HELIOS_AT_RESP_OK) { - Helios_Atcmd_Get_Para_Value_Str(resp, 1, 1, para, sizeof(para)); - return mp_obj_new_str(para, strlen(para)); - } - return mp_obj_new_int(-1); -} -static MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_reject_cause_obj, qpy_net_get_reject_cause); -#endif - - -static const mp_rom_map_elem_t net_module_globals_table[] = { - { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_net) }, - { MP_ROM_QSTR(MP_QSTR___qpy_module_deinit__), MP_ROM_PTR(&qpy_module_net_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR_csqQueryPoll), MP_ROM_PTR(&qpy_net_get_csq_obj) }, - { MP_ROM_QSTR(MP_QSTR_getState), MP_ROM_PTR(&qpy_net_get_reg_status_obj) }, - { MP_ROM_QSTR(MP_QSTR_getConfig), MP_ROM_PTR(&qpy_net_get_configuration_obj) }, - { MP_ROM_QSTR(MP_QSTR_setConfig), MP_ROM_PTR(&qpy_net_set_configuration_obj) }, - { MP_ROM_QSTR(MP_QSTR_nitzTime), MP_ROM_PTR(&qpy_net_get_nitz_time_obj) }, - { MP_ROM_QSTR(MP_QSTR_operatorName), MP_ROM_PTR(&qpy_net_get_operator_name_obj) }, - //{ MP_ROM_QSTR(MP_QSTR_setNetMode), MP_ROM_PTR(&qpy_net_set_selection_obj) }, - { MP_ROM_QSTR(MP_QSTR_getNetMode), MP_ROM_PTR(&qpy_net_get_selection_obj) }, - { MP_ROM_QSTR(MP_QSTR_getSignal), MP_ROM_PTR(&qpy_net_get_signal_strength_obj)}, - { MP_ROM_QSTR(MP_QSTR_getCellInfo), MP_ROM_PTR(&qpy_net_get_cell_info_obj) }, - { MP_ROM_QSTR(MP_QSTR_getCellInfos), MP_ROM_PTR(&qpy_net_get_cell_info_v2_obj) }, - - { MP_ROM_QSTR(MP_QSTR_getCi), MP_ROM_PTR(&qpy_net_get_cid_obj) }, - { MP_ROM_QSTR(MP_QSTR_getLac), MP_ROM_PTR(&qpy_net_get_lac_obj) }, - { MP_ROM_QSTR(MP_QSTR_getMnc), MP_ROM_PTR(&qpy_net_get_mnc_obj) }, - { MP_ROM_QSTR(MP_QSTR_getMcc), MP_ROM_PTR(&qpy_net_get_mcc_obj) }, - { MP_ROM_QSTR(MP_QSTR_setModemFun), MP_ROM_PTR(&qpy_net_set_modem_fun_obj) }, - { MP_ROM_QSTR(MP_QSTR_getModemFun), MP_ROM_PTR(&qpy_net_get_modem_fun_obj) }, - { MP_ROM_QSTR(MP_QSTR_setCallback), MP_ROM_PTR(&qpy_net_add_event_handler_obj) }, - - { MP_ROM_QSTR(MP_QSTR_setApn), MP_ROM_PTR(&qpy_net_set_apn_obj) }, - { MP_ROM_QSTR(MP_QSTR_getApn), MP_ROM_PTR(&qpy_net_get_apn_obj) }, - #if MICROPY_QPY_MODULE_NET_LED - { MP_ROM_QSTR(MP_QSTR_set_networkled_config), MP_ROM_PTR(&qpy_set_networkled_config_obj) }, - #endif - { MP_ROM_QSTR(MP_QSTR_getServingCi), MP_ROM_PTR(&qpy_net_get_cid_servingcell_obj) }, - { MP_ROM_QSTR(MP_QSTR_getServingLac), MP_ROM_PTR(&qpy_net_get_lac_servingcell_obj) }, - { MP_ROM_QSTR(MP_QSTR_getServingMnc), MP_ROM_PTR(&qpy_net_get_mnc_servingcell_obj) }, - { MP_ROM_QSTR(MP_QSTR_getServingMcc), MP_ROM_PTR(&qpy_net_get_mcc_servingcell_obj) }, -#if defined(PLAT_Qualcomm) || defined(PLAT_ASR)|| MICROPY_QPY_MODULE_NET_BAND - { MP_ROM_QSTR(MP_QSTR_setBand), MP_ROM_PTR(&qpy_net_set_band_obj) }, - { MP_ROM_QSTR(MP_QSTR_getBand), MP_ROM_PTR(&qpy_net_get_band_obj) }, -#endif -#if defined(PLAT_ASR) || MICROPY_QPY_MODULE_NET_BAND - { MP_ROM_QSTR(MP_QSTR_bandRst), MP_ROM_PTR(&qpy_net_band_restore_obj) }, -#endif - -#if MICROPY_QPY_MODULE_FTM_MODE - { MP_ROM_QSTR(MP_QSTR_ftmModeSwitch), MP_ROM_PTR(&qpy_ftm_mode_switch_obj) }, - { MP_ROM_QSTR(MP_QSTR_ftmTestStart), MP_ROM_PTR(&qpy_ftm_mode_start_obj) }, - { MP_ROM_QSTR(MP_QSTR_ftmTestStop), MP_ROM_PTR(&qpy_ftm_mode_stop_obj) }, -#endif - -#if MICROPY_QPY_MODULE_BACKCELL - { MP_ROM_QSTR(MP_QSTR_addBlackCell), MP_ROM_PTR(&qpy_add_black_cell_obj) }, - { MP_ROM_QSTR(MP_QSTR_getBlackCell), MP_ROM_PTR(&qpy_get_black_cell_obj) }, - { MP_ROM_QSTR(MP_QSTR_getBlackCellCfg), MP_ROM_PTR(&qpy_get_black_cell_cfg_obj) }, - { MP_ROM_QSTR(MP_QSTR_setBlackCellCfg), MP_ROM_PTR(&qpy_set_black_cell_cfg_obj) }, - { MP_ROM_QSTR(MP_QSTR_deleteBlackCell), MP_ROM_PTR(&qpy_delete_black_cell_obj) }, -#endif - -#if MICROPY_QPY_MODULE_DRX_TIMER - { MP_ROM_QSTR(MP_QSTR_setDrxTm), MP_ROM_PTR(&qpy_net_set_drxtm_obj) }, - { MP_ROM_QSTR(MP_QSTR_getDrxTm), MP_ROM_PTR(&qpy_net_get_drxtm_obj) }, -#endif - -#if MICROPY_QPY_MODULE_JAMDET - { MP_ROM_QSTR(MP_QSTR_setJamdetSwitch), MP_ROM_PTR(&qpy_jamdet_set_switch_obj) }, - { MP_ROM_QSTR(MP_QSTR_getJamdetSwitch), MP_ROM_PTR(&qpy_jamdet_get_switch_obj) }, - { MP_ROM_QSTR(MP_QSTR_setJamdetParam), MP_ROM_PTR(&qpy_jamdet_set_config_obj) }, - { MP_ROM_QSTR(MP_QSTR_getJamdetParam), MP_ROM_PTR(&qpy_jamdet_get_config_obj) }, - { MP_ROM_QSTR(MP_QSTR_getJamdetStatus), MP_ROM_PTR(&qpy_jamdet_get_stauts_obj) }, -#endif - -#if defined(MICROPY_QPY_MODULE_IMS_STATUS) - { MP_ROM_QSTR(MP_QSTR_getImsRegister), MP_ROM_PTR(&qpy_net_get_ims_register_obj) }, -#endif - -#if MICROPY_QPY_MODULE_NET_EX - { MP_ROM_QSTR(MP_QSTR_getT3402), MP_ROM_PTR(&qpy_net_get_T3402_obj) }, - { MP_ROM_QSTR(MP_QSTR_getT3412), MP_ROM_PTR(&qpy_net_get_T3412_obj) }, - { MP_ROM_QSTR(MP_QSTR_getT3324), MP_ROM_PTR(&qpy_net_get_T3324_obj) }, - { MP_ROM_QSTR(MP_QSTR_getTeDRX), MP_ROM_PTR(&qpy_net_get_TeDRX_obj) }, - { MP_ROM_QSTR(MP_QSTR_getTPTW), MP_ROM_PTR(&qpy_net_get_TPTW_obj) }, - { MP_ROM_QSTR(MP_QSTR_getqRxlevMin), MP_ROM_PTR(&qpy_net_get_qRxlevMin_obj) }, - { MP_ROM_QSTR(MP_QSTR_getRejectCause), MP_ROM_PTR(&qpy_net_get_reject_cause_obj) }, -#endif -}; - -static MP_DEFINE_CONST_DICT(net_module_globals, net_module_globals_table); -const mp_obj_module_t mp_module_net = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t *)&net_module_globals, -}; - -MP_REGISTER_MODULE(MP_QSTR_net, mp_module_net); -#endif /* MICROPY_QPY_MODULE_NET */ diff --git a/ports/quectel/modostimer.c b/ports/quectel/modostimer.c deleted file mode 100644 index 8fcce2a3f4c86..0000000000000 --- a/ports/quectel/modostimer.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020-2021 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 -#include "py/compile.h" -#include "py/nlr.h" -#include "py/objlist.h" -#include "py/objstr.h" -#include "py/runtime.h" -#include "py/mperrno.h" -#include "py/mphal.h" -#include "py/stream.h" -#include "py/obj.h" - -#if MICROPY_QPY_MODULE_OSTIMER - -#include "helios_os.h" -#include "helios_debug.h" - -#define HELIOS_OSTIMER_LOG(msg, ...) custom_log("osTimer", msg, ##__VA_ARGS__) - - -typedef struct _mod_ostimer_obj_t -{ - mp_obj_base_t base; - Helios_OSTimer_t handle; /* OS supplied timer reference */ - unsigned int initialTime; /* initial expiration time in ms */ - bool cyclicalEn; /* wether to enable the cyclical mode or not */ - c_callback_t callback; /* timer call-back routine */ - bool deleteFlagh; -} mod_ostimer_obj_t; - -const mp_obj_type_t mp_ostimer_type; - -STATIC void mod_ostimer_isr(void *cb) { - c_callback_t *callback = (c_callback_t *)cb; - if(NULL != callback){ - mp_sched_schedule_ex(callback, mp_const_none); - } -} - - -STATIC mp_obj_t mod_ostimer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) -{ - mod_ostimer_obj_t *timer = mp_obj_malloc_with_finaliser(mod_ostimer_obj_t); - - timer->base.type = &mp_ostimer_type; - timer->handle = Helios_OSTimer_Create(); - timer->deleteFlagh = 0; - - return MP_OBJ_FROM_PTR(timer); -} - - -STATIC mp_obj_t mod_ostimer_start(uint n_args, const mp_obj_t *args) -{ - int ret = 0; - - mod_ostimer_obj_t *self = MP_OBJ_TO_PTR(args[0]); - - if (!(self->deleteFlagh)) - { - self->initialTime = mp_obj_get_int(args[1]); - - self->cyclicalEn = !!mp_obj_get_int(args[2]); - - //self->callback = args[3]; - mp_sched_schedule_callback_register(&self->callback, args[3]); - - Helios_OSTimerAttr OSTimerAttr = { - .ms = (uint32_t)self->initialTime, - .cycle_enable = self->cyclicalEn, - .cb = mod_ostimer_isr, - .argv = (void *)&self->callback - }; - ret = Helios_OSTimer_Start(self->handle, &OSTimerAttr); - } - else - { - ret = -1; - } - return mp_obj_new_int(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_ostimer_start_obj, 3, 5, mod_ostimer_start); - -STATIC mp_obj_t mod_ostimer_stop(mp_obj_t arg0) -{ - int ret = 0; - - mod_ostimer_obj_t *self = MP_OBJ_TO_PTR(arg0); - if (!(self->deleteFlagh)) - { - ret = Helios_OSTimer_Stop(self->handle); - } - else - { - ret = -1; - } - return mp_obj_new_int(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ostimer_stop_obj, mod_ostimer_stop); - - - -STATIC mp_obj_t mod_ostimer_delete(mp_obj_t arg0) -{ - int ret = 0; - - mod_ostimer_obj_t *self = MP_OBJ_TO_PTR(arg0); - - if (!(self->deleteFlagh)) - { - self->deleteFlagh = 1; - Helios_OSTimer_Delete(self->handle); - HELIOS_OSTIMER_LOG("[osTimer] ostimer delete\r\n"); - } - - return mp_obj_new_int(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ostimer_delete_obj, mod_ostimer_delete); - - -STATIC const mp_rom_map_elem_t mod_ostimer_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_osTimer) }, - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_ostimer_delete_obj) }, - { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&mod_ostimer_start_obj) }, - { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&mod_ostimer_stop_obj) }, - { MP_ROM_QSTR(MP_QSTR_delete_timer), MP_ROM_PTR(&mod_ostimer_delete_obj) }, -}; -STATIC MP_DEFINE_CONST_DICT(mod_ostimer_locals_dict, mod_ostimer_locals_dict_table); - - -const mp_obj_type_t mp_ostimer_type = { - { &mp_type_type }, - .name = MP_QSTR_osTimer, - .make_new = mod_ostimer_make_new, - .locals_dict = (mp_obj_dict_t *)&mod_ostimer_locals_dict, -}; - - -#endif /* MICROPY_QPY_MODULE_OSTIMER */ diff --git a/ports/quectel/modsim.c b/ports/quectel/modsim.c deleted file mode 100644 index 691d7ab02b5d3..0000000000000 --- a/ports/quectel/modsim.c +++ /dev/null @@ -1,1128 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020-2021 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 "stdio.h" -#include "stdlib.h" -#include "obj.h" -#include "runtime.h" -#include "mphalport.h" - -#if MICROPY_QPY_MODULE_SIM - -#include "helios_debug.h" -#include "helios_sim.h" - -#if MICROPY_QPY_MODULE_ESIM_SIM_SWITCH -#include "rt_lpa.h" -#include "rt_port_at.h" -#include "rt_utils.h" - -#define MAX_EID_HEX_LEN 16 -#define MAX_EID_LEN 33 -#define THE_MAX_CARD_NUM 20 -#endif - -#define QPY_MODSIM_LOG(msg, ...) custom_log("SIM", msg, ##__VA_ARGS__) - - -static void toUpperCase(char *str) -{ - while (*str != '\0') { - if(*str >='a' && *str <= 'z') { - *str -= 32; - } - str++; - } -} - -int _get_current_simid(void) -{ - int cur_simid = 0; - -#if defined(PLAT_ASR) ||defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_Unisoc_8850_R02) || defined(PLAT_EIGEN) || defined(PLAT_ASR_1602) || defined(PLAT_EIGEN_718) - - uint8_t sim_id = 0; - MP_THREAD_GIL_EXIT(); - Helios_SIM_GetCurrentSimid(&sim_id); - MP_THREAD_GIL_ENTER(); - cur_simid = sim_id; -#elif defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) - cur_simid = 0; -#endif - - if(cur_simid < 0) - { - cur_simid = 0; - } - - return cur_simid; -} -/*=============================================================================*/ -/* FUNCTION: qpy_sim_get_imsi */ -/*=============================================================================*/ -/*!@brief: Get the IMSI of the SIM card - * - * @return: - * if get successfully, return the IMSI - * -1 - error - */ -/*=============================================================================*/ -static mp_obj_t qpy_sim_get_imsi(size_t n_args, const mp_obj_t *args) -{ - int cur_simid = 0; - char imsi_str[HELIOS_SIM_IMSI_LEN+1] = {0}; - uint8_t status = 0; - int ret = 0; - if ( n_args > 0 ) - { - cur_simid = mp_obj_get_int(args[0]); - }else{ - cur_simid = _get_current_simid(); - } - if ((cur_simid != 0) && (cur_simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); - } - MP_THREAD_GIL_EXIT(); - Helios_SIM_GetCardStatus(cur_simid, (Helios_SIM_Status_e *)&status); - MP_THREAD_GIL_ENTER(); - if (ret == 0) - { - if (status != 1) - { - return mp_obj_new_int(-1); - } - } - else - { - return mp_obj_new_int(-1); - } - MP_THREAD_GIL_EXIT(); - ret = Helios_SIM_GetIMSI(cur_simid, (void *)imsi_str, sizeof(imsi_str)); - MP_THREAD_GIL_ENTER(); - if (ret == 0) - { - return mp_obj_new_str(imsi_str, strlen(imsi_str)); - } - - return mp_obj_new_int(-1); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_sim_get_imsi_obj, 0, 1, qpy_sim_get_imsi); - - -/*=============================================================================*/ -/* FUNCTION: qpy_sim_get_iccid */ -/*=============================================================================*/ -/*!@brief: Get the ICCID of the SIM card - * - * @return: - * if get successfully, return the ICCID - * -1 - error - */ -/*=============================================================================*/ -static mp_obj_t qpy_sim_get_iccid(size_t n_args, const mp_obj_t *args) -{ - char iccid_str[HELIOS_SIM_ICCID_LEN+1] = {0}; - uint8_t status = 0; - int ret = 0; - int cur_simid = 0; - if ( n_args > 0 ) - { - cur_simid = mp_obj_get_int(args[0]); - }else{ - cur_simid = _get_current_simid(); - } - if ((cur_simid != 0) && (cur_simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); - } - MP_THREAD_GIL_EXIT(); - Helios_SIM_GetCardStatus(cur_simid, (Helios_SIM_Status_e *)&status); - MP_THREAD_GIL_ENTER(); - if (ret == 0) - { - if (status != 1) - { - return mp_obj_new_int(-1); - } - } - else - { - return mp_obj_new_int(-1); - } - MP_THREAD_GIL_EXIT(); - ret = Helios_SIM_GetICCID(cur_simid, (void *)iccid_str, sizeof(iccid_str)); - MP_THREAD_GIL_ENTER(); - if (ret == 0) - { - toUpperCase(iccid_str); - return mp_obj_new_str(iccid_str, strlen(iccid_str)); - } - - return mp_obj_new_int(-1); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_sim_get_iccid_obj, 0, 1, qpy_sim_get_iccid); - - -/*=============================================================================*/ -/* FUNCTION: qpy_sim_get_phonenumber */ -/*=============================================================================*/ -/*!@brief: Get the phone number of the SIM card - * - * @return: - * if get successfully, return the phone number - * -1 - error - */ -/*=============================================================================*/ -static mp_obj_t qpy_sim_get_phonenumber(size_t n_args, const mp_obj_t *args) -{ - char phone_number[HELIOS_SIM_PHONENUM_LEN+1] = {0}; - int ret = 0; - int cur_simid = 0; - if ( n_args > 0 ) - { - cur_simid = mp_obj_get_int(args[0]); - }else{ - cur_simid = _get_current_simid(); - } - if ((cur_simid != 0) && (cur_simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); - } - MP_THREAD_GIL_EXIT(); - ret = Helios_SIM_GetPhoneNumber(cur_simid, (void *)phone_number, sizeof(phone_number)); - MP_THREAD_GIL_ENTER(); - if (ret == 0) - { - return mp_obj_new_str(phone_number, strlen(phone_number)); - } - - return mp_obj_new_int(-1); -} - -#if !defined (PLAT_RDA) -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_sim_get_phonenumber_obj, 0, 1, qpy_sim_get_phonenumber); -#endif -/*=============================================================================*/ -/* FUNCTION: qpy_sim_enable_pin */ -/*=============================================================================*/ -/*!@brief: enable SIM card PIN code verification, and restart will take effect - * - * @pin [in] PIN code - * @return: - * 0 - success - * -1 - error - */ -/*=============================================================================*/ -#ifndef MICROPY_QPY_MODULE_NO_SIMPIN -static mp_obj_t qpy_sim_enable_pin(size_t n_args, const mp_obj_t *args) -{ - Helios_SIMPinInfoStruct info = {0}; - mp_buffer_info_t bufinfo = {0}; - int cur_simid = 0; - if ( n_args > 1 ) - { - cur_simid = mp_obj_get_int(args[1]); - }else{ - cur_simid = _get_current_simid(); - } - if ((cur_simid != 0) && (cur_simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); - } - mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ); - if (bufinfo.len > HELIOS_SIM_PIN_LEN_MAX) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, the length of pin should be no more than [%d] bytes."), HELIOS_SIM_PIN_LEN_MAX); - } - - strncpy((char *)info.pin, (const char *)bufinfo.buf, bufinfo.len); - - - MP_THREAD_GIL_EXIT(); - int ret = Helios_SIM_PINEnable(cur_simid, &info); - MP_THREAD_GIL_ENTER(); - if (ret == 0) - { - return mp_obj_new_int(ret); - } - - return mp_obj_new_int(-1); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_sim_enable_pin_obj, 1, 2, qpy_sim_enable_pin); - - -/*=============================================================================*/ -/* FUNCTION: qpy_sim_disable_pin */ -/*=============================================================================*/ -/*!@brief: disable SIM card PIN code verification - * - * @pin [in] PIN code - * @return: - * 0 - success - * -1 - error - */ -/*=============================================================================*/ -static mp_obj_t qpy_sim_disable_pin(size_t n_args, const mp_obj_t *args) -{ - Helios_SIMPinInfoStruct info = {0}; - mp_buffer_info_t bufinfo = {0}; - int cur_simid = 0; - if ( n_args > 1 ) - { - cur_simid = mp_obj_get_int(args[1]); - }else{ - cur_simid = _get_current_simid(); - } - - mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ); - if (bufinfo.len > HELIOS_SIM_PIN_LEN_MAX) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, the length of pin should be no more than [%d] bytes."), HELIOS_SIM_PIN_LEN_MAX); - } - if ((cur_simid != 0) && (cur_simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); - } - strncpy((char *)info.pin, (const char *)bufinfo.buf, bufinfo.len); - - MP_THREAD_GIL_EXIT(); - int ret = Helios_SIM_PINDisable(cur_simid, &info); - MP_THREAD_GIL_ENTER(); - if (ret == 0) - { - return mp_obj_new_int(ret); - } - - return mp_obj_new_int(-1); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_sim_disable_pin_obj, 1, 2, qpy_sim_disable_pin); - - -/*=============================================================================*/ -/* FUNCTION: qpy_sim_verify_pin */ -/*=============================================================================*/ -/*!@brief: when the SIM state is requested PIN/PIN2, enter the PIN/PIN2 code to verify - * - * @pin [in] PIN code - * @return: - * 0 - success - * -1 - error - */ -/*=============================================================================*/ -static mp_obj_t qpy_sim_verify_pin(size_t n_args, const mp_obj_t *args) -{ - Helios_SIMPinInfoStruct info = {0}; - mp_buffer_info_t bufinfo = {0}; - int cur_simid = 0; - if ( n_args > 1 ) - { - cur_simid = mp_obj_get_int(args[1]); - }else{ - cur_simid = _get_current_simid(); - } - mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ); - - if (bufinfo.len > HELIOS_SIM_PIN_LEN_MAX) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, the length of pin should be no more than [%d] bytes."), HELIOS_SIM_PIN_LEN_MAX); - } - if ((cur_simid != 0) && (cur_simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); - } - strncpy((char *)info.pin, (const char *)bufinfo.buf, bufinfo.len); - - MP_THREAD_GIL_EXIT(); - int ret = Helios_SIM_PINVerify(cur_simid, &info); - MP_THREAD_GIL_ENTER(); - if (ret == 0) - { - return mp_obj_new_int(ret); - } - - return mp_obj_new_int(-1); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_sim_verify_pin_obj, 1, 2,qpy_sim_verify_pin); - -/*=============================================================================*/ -/* FUNCTION: qpy_sim_change_pin */ -/*=============================================================================*/ -/*!@brief: After enabling SIM card PIN verification, change the SIM card PIN - * - * @old_pin [in] old PIN - * @new_pin [in] new PIN - * @return: - * 0 - success - * -1 - error - */ -/*=============================================================================*/ - -static mp_obj_t qpy_sim_change_pin(size_t n_args, const mp_obj_t *args) -{ - Helios_SIMChangePinInfoStruct info = {0}; - mp_buffer_info_t bufinfo[2] = {0}; - int cur_simid = 0; - if ( n_args > 2 ) - { - cur_simid = mp_obj_get_int(args[2]); - }else{ - cur_simid = _get_current_simid(); - } - mp_get_buffer_raise(args[0], &bufinfo[0], MP_BUFFER_READ); - mp_get_buffer_raise(args[1], &bufinfo[1], MP_BUFFER_READ); - - if ((bufinfo[0].len > HELIOS_SIM_PIN_LEN_MAX) || (bufinfo[1].len > HELIOS_SIM_PIN_LEN_MAX)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, the length of pin should be no more than [%d] bytes."), HELIOS_SIM_PIN_LEN_MAX); - } - if ((cur_simid != 0) && (cur_simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); - } - strncpy((char *)info.old_pin, (const char *)bufinfo[0].buf, bufinfo[0].len); - strncpy((char *)info.new_pin, (const char *)bufinfo[1].buf, bufinfo[1].len); - - MP_THREAD_GIL_EXIT(); - int ret = Helios_SIM_PINChange(cur_simid, &info); - MP_THREAD_GIL_ENTER(); - if (ret == 0) - { - return mp_obj_new_int(ret); - } - - return mp_obj_new_int(-1); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_sim_change_pin_obj, 2,3,qpy_sim_change_pin); - - -/*=============================================================================*/ -/* FUNCTION: qpy_sim_unblock_pin */ -/*=============================================================================*/ -/*!@brief: When the SIM card status is requested PUK/PUK2 after multiple incorrect input - * of PIN/PIN2 code, input PUK/PUK2 code and a new PIN/PIN2 code to unlock - * - * @puk [in] PUK/PUK2 - * @new_pin [in] new PIN/PIN2 - * @return: - * 0 - success - * -1 - error - */ -/*=============================================================================*/ -static mp_obj_t qpy_sim_unblock_pin(size_t n_args, const mp_obj_t *args) -{ - Helios_SIMUnlockPinInfoStruct info = {0}; - mp_buffer_info_t bufinfo[2] = {0}; - - int cur_simid = 0; - if ( n_args > 2 ) - { - cur_simid = mp_obj_get_int(args[2]); - }else{ - cur_simid = _get_current_simid(); - - } - mp_get_buffer_raise(args[0], &bufinfo[0], MP_BUFFER_READ); - - - mp_get_buffer_raise(args[1], &bufinfo[1], MP_BUFFER_READ); - - - if ((bufinfo[0].len > HELIOS_SIM_PIN_LEN_MAX) || (bufinfo[1].len > HELIOS_SIM_PIN_LEN_MAX)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, the length of pin or puk should be no more than [%d] bytes."), HELIOS_SIM_PIN_LEN_MAX); - } - if ((cur_simid != 0) && (cur_simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); - } - strncpy((char *)info.puk, (const char *)bufinfo[0].buf, bufinfo[0].len); - strncpy((char *)info.new_pin, (const char *)bufinfo[1].buf, bufinfo[1].len); - - MP_THREAD_GIL_EXIT(); - int ret = Helios_SIM_PINUnlock(cur_simid, &info); - MP_THREAD_GIL_ENTER(); - if (ret == 0) - { - return mp_obj_new_int(ret); - } - - return mp_obj_new_int(-1); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_sim_unblock_pin_obj, 2, 3, qpy_sim_unblock_pin); -#endif - -#if MICROPY_QPY_MODULE_PIN_REMATTEMPTS - -static mp_obj_t qpy_sim_pin_remain_attempts(size_t n_args, const mp_obj_t *args) -{ - Helios_SIMRemainPinAttempts info = {0}; - - uint8_t cur_simid = _get_current_simid(); - MP_THREAD_GIL_EXIT(); - int ret = Helios_SIM_PINRemainAttempts(cur_simid, &info); - MP_THREAD_GIL_ENTER(); - if (ret == 0) - { - if (n_args > 0) - { - int flag = mp_obj_get_int(args[0]); - if (flag == 0) - { - mp_obj_t tuple[2] = { - mp_obj_new_int(info.pin_remain_attempts), - mp_obj_new_int(info.puk_remain_attempts) - }; - return mp_obj_new_tuple(2, tuple); - } - else if (flag == 1) - { - mp_obj_t tuple[4] = { - mp_obj_new_int(info.pin_remain_attempts), - mp_obj_new_int(info.puk_remain_attempts), - mp_obj_new_int(info.pin2_remain_attempts), - mp_obj_new_int(info.puk2_remain_attempts) - }; - return mp_obj_new_tuple(4, tuple); - } - else - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, flag should be in [0,1].")); - } - } - else - { - mp_obj_t tuple[2] = { - mp_obj_new_int(info.pin_remain_attempts), - mp_obj_new_int(info.puk_remain_attempts) - }; - return mp_obj_new_tuple(2, tuple); - } - } - return mp_obj_new_int(-1); - -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_sim_pin_remain_attempts_obj, 0, 1, qpy_sim_pin_remain_attempts); - -#endif -/*=============================================================================*/ -/* FUNCTION: sim_get_card_status */ -/*=============================================================================*/ -/*!@brief: Get the status of the SIM card. - * - * @return : - * - 0 SIM was removed. - * - 1 SIM is ready. - * - 2 Expecting the universal PIN./SIM is locked, waiting for a CHV1 password. - * - 3 Expecting code to unblock the universal PIN./SIM is blocked, CHV1 unblocking password is required. - * - 4 SIM is locked due to a SIM/USIM personalization check failure. - * - 5 SIM is blocked due to an incorrect PCK; an MEP unblocking password is required. - * - 6 Expecting key for hidden phone book entries. - * - 7 Expecting code to unblock the hidden key. - * - 8 SIM is locked; waiting for a CHV2 password. - * - 9 SIM is blocked; CHV2 unblocking password is required. - * - 10 SIM is locked due to a network personalization check failure. - * - 11 SIM is blocked due to an incorrect NCK; an MEP unblocking password is required. - * - 12 -SIM is locked due to a network subset personalization check failure. - * - 13 SIM is blocked due to an incorrect NSCK; an MEP unblocking password is required. - * - 14 SIM is locked due to a service provider personalization check failure. - * - 15 SIM is blocked due to an incorrect SPCK; an MEP unblocking password is required. - * - 16 SIM is locked due to a corporate personalization check failure. - * - 17 SIM is blocked due to an incorrect CCK; an MEP unblocking password is required. - * - 18 SIM is being initialized; waiting for completion. - * - 19 Use of CHV1/CHV2/universal PIN/code to unblock the CHV1/code to unblock the CHV2/code to unblock the universal PIN/ is blocked. - * - 20 Unuseful status. - * - 21 Unknow status. - */ - /*=============================================================================*/ - -static mp_obj_t qpy_sim_get_card_status(size_t n_args, const mp_obj_t *args) -{ - Helios_SIM_Status_e status = 0; - int ret = 0; - int cur_simid = 0 ; - if ( n_args > 0 ) - { - cur_simid = (uint8_t)mp_obj_get_int(args[0]); - }else{ - cur_simid = _get_current_simid(); - } - if ((cur_simid != 0) && (cur_simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); - } - MP_THREAD_GIL_EXIT(); - ret = Helios_SIM_GetCardStatus(cur_simid, &status); - MP_THREAD_GIL_ENTER(); - if (ret == 0) - { - return mp_obj_new_int(status); - } - return mp_obj_new_int(-1); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_sim_get_card_status_obj, 0, 1, qpy_sim_get_card_status); - -#if MICROPY_QPY_MODULE_PHB -static mp_obj_t qpy_sim_get_phonebookstatus(void) -{ - uint8_t pb_ready_flag = 0; - MP_THREAD_GIL_EXIT(); - Helios_SIM_GetPbReady(&pb_ready_flag); - MP_THREAD_GIL_ENTER(); - return mp_obj_new_int(pb_ready_flag); -} -static MP_DEFINE_CONST_FUN_OBJ_0(qpy_sim_get_phonebookstatus_obj, qpy_sim_get_phonebookstatus); -/*=============================================================================*/ -/* FUNCTION: qpy_sim_read_phonebook_record */ -/*=============================================================================*/ -/*!@brief : Read the phone book. - * - * @args[1] [in] the storage position of the phone book. - * @args[2] [in] start_index - * @args[3] [in] end_index - * @args[4] [in] username - * @return : - * -1 - error - * If it reads successfully, the results are returned in the following format. - * (record_number, [(index, username, phone_number), ... , (index, username, phone_number)]) - * For example: - * (2, [(1, 'zhangsan', '18122483511'), (2, 'lisi', '18122483542')]) - */ -/*=============================================================================*/ - -static mp_obj_t qpy_sim_read_phonebook_record(size_t n_args, const mp_obj_t *args) -{ - uint8_t i = 0; - int32_t storage = 0; - int cur_simid = 0; - Helios_SIMReadPhoneBookInfoStruct records = {0}; - mp_buffer_info_t nameinfo = {0}; - mp_obj_t list_records = mp_obj_new_list(0, NULL); - - if ( n_args > 4 ){ - cur_simid = mp_obj_get_int(args[4]); - }else{ - cur_simid = _get_current_simid(); - } - storage = mp_obj_get_int(args[0]); - records.start_index = mp_obj_get_int(args[1]); - records.end_index = mp_obj_get_int(args[2]); - mp_get_buffer_raise(args[3], &nameinfo, MP_BUFFER_READ); - - if ((storage < 0) || (storage > 15)) - { - mp_raise_ValueError(MP_ERROR_TEXT("invalid value, storage should be in (0,15).")); - } - if (records.end_index < records.start_index) - { - mp_raise_ValueError(MP_ERROR_TEXT("invalid value, end >= start.")); - } - if ((records.end_index - records.start_index) > 20) - { - mp_raise_ValueError(MP_ERROR_TEXT("invalid value, end - start <= 20.")); - } - if ((cur_simid != 0) && (cur_simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); - } - if (nameinfo.len > 30) - { - mp_raise_ValueError(MP_ERROR_TEXT("invalid value, the length of username should be no more than 30 bytes.")); - } - records.user_name = (char *)nameinfo.buf; - - MP_THREAD_GIL_EXIT(); - int ret = Helios_SIM_ReadPhonebookRecord(cur_simid, storage, &records); - MP_THREAD_GIL_ENTER(); - if (ret == 0) - { - for (i=0; i 4 ){ - cur_simid = mp_obj_get_int(args[4]); - } else{ - cur_simid = _get_current_simid(); - } - storage = mp_obj_get_int(args[0]); - record.index = mp_obj_get_int(args[1]); - mp_get_buffer_raise(args[2], &bufinfo[0], MP_BUFFER_READ); - mp_get_buffer_raise(args[3], &bufinfo[1], MP_BUFFER_READ); - - if ((storage < 0) || (storage > 15)) - { - mp_raise_ValueError(MP_ERROR_TEXT("invalid value, storage should be in (0,15).")); - } - if ((record.index < 1) || (record.index > 500)) - { - mp_raise_ValueError(MP_ERROR_TEXT("invalid value, index should be in (1,500).")); - } - if (bufinfo[0].len > 30) - { - mp_raise_ValueError(MP_ERROR_TEXT("invalid value, the length of username should be no more than 30 bytes.")); - } - if (bufinfo[1].len > 20) - { - mp_raise_ValueError(MP_ERROR_TEXT("invalid value, the length of phonenumber should be no more than 20 bytes.")); - } - if ((cur_simid != 0) && (cur_simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); - } - strncpy(record.user_name, bufinfo[0].buf, bufinfo[0].len); - strncpy(record.phone_num, bufinfo[1].buf, bufinfo[1].len); - - - MP_THREAD_GIL_EXIT(); - int ret = Helios_SIM_WritePhonebookRecord(cur_simid, storage, &record); - MP_THREAD_GIL_ENTER(); - if (ret == 0) - { - return mp_obj_new_int(0); - } - return mp_obj_new_int(-1); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_sim_write_phonebook_record_obj, 3,5, qpy_sim_write_phonebook_record); - -#endif - - -#if MICROPY_QPY_MODULE_SIMDET -static mp_obj_t qpy_sim_set_simdet(size_t n_args, const mp_obj_t *args) -{ - int ret = 0; - int cur_simid = 0; - - int detenable = 0; - int insertlevel = 0; - if ( n_args > 2 ){ - cur_simid = mp_obj_get_int(args[2]); - }else{ - cur_simid = _get_current_simid(); - } - detenable = mp_obj_get_int(args[0]); - insertlevel = mp_obj_get_int(args[1]); - - if (detenable != 0 && detenable != 1) - { - mp_raise_ValueError(MP_ERROR_TEXT("invalid value, detenable should be in (0,1).")); - } - if (insertlevel != 0 && insertlevel != 1) - { - mp_raise_ValueError(MP_ERROR_TEXT("invalid value, insertlevel should be in (0,1).")); - } - if ((cur_simid != 0) && (cur_simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); - } - MP_THREAD_GIL_EXIT(); - ret = Helios_SIM_SetSimDet(cur_simid, detenable, insertlevel); - MP_THREAD_GIL_ENTER(); - if (ret == 0) - { - return mp_obj_new_int(ret); - } - - return mp_obj_new_int(-1); -} - -static mp_obj_t qpy_sim_get_simdet(size_t n_args, const mp_obj_t *args) -{ - int ret = 0; - int detenable = 99; - int insertlevel = 99; - int cur_simid = 0; - if ( n_args > 0 ){ - cur_simid = mp_obj_get_int(args[0]); - }else{ - cur_simid = _get_current_simid(); - } - if ((cur_simid != 0) && (cur_simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simId should be in [0~1].")); - } - MP_THREAD_GIL_EXIT(); - ret = Helios_SIM_GetSimDet(cur_simid, &detenable, &insertlevel); - MP_THREAD_GIL_ENTER(); - if (ret == 0) - { - mp_obj_t tuple[2] = - { - mp_obj_new_int(detenable), - mp_obj_new_int(insertlevel), - }; - return mp_obj_new_tuple(2, tuple); - } - - return mp_obj_new_int(-1); -} - -static c_callback_t *g_sim_user_callback; - -static void qpy_sim_event_handler(uint8_t sim_id, unsigned int event_id, void *ctx) -{ - if(g_sim_user_callback) - { - QPY_MODSIM_LOG("[SIM] callback start.\r\n"); - GC_STACKTOP_SET(); - mp_sched_schedule_ex(g_sim_user_callback, mp_obj_new_int(event_id)); - GC_STACKTOP_CLEAR(); - QPY_MODSIM_LOG("[SIM] callback end.\r\n"); - } -} - -static mp_obj_t qpy_sim_add_event_handler(mp_obj_t handler) -{ - static c_callback_t cb = {0}; - memset(&cb, 0, sizeof(c_callback_t)); - g_sim_user_callback = &cb; - mp_sched_schedule_callback_register(g_sim_user_callback, handler); - MP_THREAD_GIL_EXIT(); - Helios_SIM_Add_Event_Handler(qpy_sim_event_handler); - MP_THREAD_GIL_ENTER(); - return mp_obj_new_int(0); -} - -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_sim_set_simdet_obj, 2, 3, qpy_sim_set_simdet); - -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_sim_get_simdet_obj, 0, 1, qpy_sim_get_simdet); - -static MP_DEFINE_CONST_FUN_OBJ_1(qpy_sim_add_event_handler_obj, qpy_sim_add_event_handler); -#endif - -#if defined(PLAT_ASR) -static mp_obj_t qpy_sim_genericaccess(const mp_obj_t sim_id, const mp_obj_t cmd) -{ - Helios_SIMGenericAccesStruct info = {0}; - int simid = mp_obj_get_int(sim_id); - mp_buffer_info_t bufinfo = {0}; - mp_get_buffer_raise(cmd, &bufinfo, MP_BUFFER_READ); - - if (bufinfo.len <= 0) - { - mp_raise_ValueError(MP_ERROR_TEXT("invalid value, the length of cmd should be more than 0 bytes.")); - } - - if (simid != 0) - { - mp_raise_ValueError(MP_ERROR_TEXT("invalid simid.")); - } - - strncpy((char *)info.cmd, (const char *)bufinfo.buf, bufinfo.len); - info.len = bufinfo.len; - MP_THREAD_GIL_EXIT(); - int ret = Helios_SIM_GenericAccess(simid, &info); - MP_THREAD_GIL_ENTER(); - if (ret == 0) - { - mp_obj_t tuple[2] = - { - mp_obj_new_int(strlen(info.resp)), - mp_obj_new_str(info.resp, strlen(info.resp)), - }; - return mp_obj_new_tuple(2, tuple); - //return mp_obj_new_str(info.resp, strlen(info.resp)); - } - return mp_obj_new_int(-1); -} -static MP_DEFINE_CONST_FUN_OBJ_2(qpy_sim_genericaccess_obj, qpy_sim_genericaccess); -#endif - -#if MICROPY_QPY_MODULE_DUALSIM || MICROPY_QPY_MODULE_DSDS -static c_callback_t * g_switchsim_done_callback; - -static void switch_sim_done_callback(uint8_t state) -{ - if (g_switchsim_done_callback) - { - GC_STACKTOP_SET(); - mp_sched_schedule_ex(g_switchsim_done_callback, mp_obj_new_int(state)); - GC_STACKTOP_CLEAR(); - } -} - -static mp_obj_t qpy_sim_set_switchcard_cb(mp_obj_t switchsim_callback) -{ - static c_callback_t cb = {0}; - memset(&cb, 0, sizeof(c_callback_t)); - g_switchsim_done_callback = &cb; - mp_sched_schedule_callback_register(g_switchsim_done_callback, switchsim_callback); - - return mp_obj_new_int(0); -} -static MP_DEFINE_CONST_FUN_OBJ_1(qpy_sim_set_switchcard_cb_obj, qpy_sim_set_switchcard_cb); - -static mp_obj_t qpy_sim_switch_card(mp_obj_t sim_id) -{ - uint8_t simid = mp_obj_get_int(sim_id); - if ((simid != 0) && (simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simid should be in [0,1].")); - } -#if MICROPY_QPY_MODULE_DUALSIM - uint8_t old_simid = HELIOS_SIM_0; - MP_THREAD_GIL_EXIT(); - Helios_SIM_GetCurrentSimid(&old_simid); - MP_THREAD_GIL_ENTER(); - if (simid == old_simid) - { - return mp_obj_new_int(-1); - } -#endif - MP_THREAD_GIL_EXIT(); - int ret = Helios_SIM_SwitchCard(simid, switch_sim_done_callback); - MP_THREAD_GIL_ENTER(); - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_1(qpy_sim_switch_card_obj, qpy_sim_switch_card); - -static mp_obj_t qpy_sim_get_current_simid() -{ - uint8_t simid = HELIOS_SIM_0; - MP_THREAD_GIL_EXIT(); - Helios_SIM_GetCurrentSimid(&simid); - MP_THREAD_GIL_ENTER(); - return mp_obj_new_int(simid); -} -static MP_DEFINE_CONST_FUN_OBJ_0(qpy_sim_get_current_simid_obj, qpy_sim_get_current_simid); - -#if defined(BOARD_EC800MCN_LE_VOLVGL) || defined(BOARD_EC800MCN_LE_CPE) || defined(BOARD_EG810MEU_LA_VOLVGL) -static mp_obj_t qpy_sim_is_insert(mp_obj_t sim_id) -{ - int simid = mp_obj_get_int(sim_id); - if ((simid != 0) && (simid != 1)) - { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid value, simid should be in [0,1].")); - } - uint8_t insert_sta = 0; - MP_THREAD_GIL_EXIT(); - Helios_SIM_GetInsertStatus(simid, &insert_sta); - MP_THREAD_GIL_ENTER(); - return mp_obj_new_bool(insert_sta); -} -static MP_DEFINE_CONST_FUN_OBJ_1(qpy_sim_is_insert_obj, qpy_sim_is_insert); -#endif - -#endif - -static mp_obj_t qpy_module_sim_deinit(void) -{ - #if MICROPY_QPY_MODULE_DUALSIM || MICROPY_QPY_MODULE_DSDS - g_switchsim_done_callback = NULL; - #endif - - #if MICROPY_QPY_MODULE_SIMDET - g_sim_user_callback = NULL; - MP_THREAD_GIL_EXIT(); - Helios_SIM_Add_Event_Handler(NULL); - MP_THREAD_GIL_ENTER(); - #endif - - return mp_obj_new_int(0); -} - -static MP_DEFINE_CONST_FUN_OBJ_0(qpy_module_sim_deinit_obj, qpy_module_sim_deinit); - -#if MICROPY_QPY_MODULE_ESIM_SIM_SWITCH -static mp_obj_t qpy_sim_get_esim_list(void) -{ - int ret = 0; - u08 profile_num =0; - profile_info_t card_info[THE_MAX_CARD_NUM] = {0}; - mp_obj_t list_profile = mp_obj_new_list(0, NULL); - MP_THREAD_GIL_EXIT(); - ret = rt_lpa_get_profile_info(card_info, &profile_num, THE_MAX_CARD_NUM); - MP_THREAD_GIL_ENTER(); - if (ret == 0) - { - int i = 0; - for (i = 0; i < profile_num; i++) - { - mp_obj_t profile_info[3] = { - mp_obj_new_str(card_info[i].iccid, strlen(card_info[i].iccid)), - mp_obj_new_int(card_info[i].state), - mp_obj_new_int(card_info[i].class)}; - mp_obj_list_append(list_profile, mp_obj_new_tuple(3, profile_info)); - } - } - mp_obj_t tuple[2] = - { - mp_obj_new_int(profile_num), - list_profile, - }; - return mp_obj_new_tuple(2, tuple); -} -static MP_DEFINE_CONST_FUN_OBJ_0(qpy_sim_get_esim_list_obj, qpy_sim_get_esim_list); - - -static mp_obj_t qpy_sim_get_esim_eid(void) -{ - char eid_buf[MAX_EID_HEX_LEN] = {0}; - char eid[MAX_EID_LEN] = {0}; - int ret = -1; - MP_THREAD_GIL_EXIT(); - ret = rt_lpa_get_eid((u08 *)eid_buf); - rt_utils_bytes_to_hex((cpu08)eid_buf, sizeof(eid_buf), eid); - MP_THREAD_GIL_ENTER(); - if (ret != 0) - { - memset(eid, 0, sizeof(eid)); - } - return mp_obj_new_str(eid, strlen(eid)); -} -static MP_DEFINE_CONST_FUN_OBJ_0(qpy_sim_get_esim_eid_obj, qpy_sim_get_esim_eid); - -static mp_obj_t qpy_sim_enable_esim(const mp_obj_t iccid) -{ - int ret = -1; - mp_buffer_info_t qpy_iccid = {0}; - mp_get_buffer_raise(iccid, &qpy_iccid, MP_BUFFER_READ); - - if (qpy_iccid.len != 20) - { - mp_raise_ValueError(MP_ERROR_TEXT("invalid value, the length of iccid should be 20 bytes.")); - } - MP_THREAD_GIL_EXIT(); - ret = rt_lpa_enable_profile(qpy_iccid.buf); - MP_THREAD_GIL_ENTER(); - return mp_obj_new_int(ret); -} -static MP_DEFINE_CONST_FUN_OBJ_1(qpy_sim_enable_esim_obj, qpy_sim_enable_esim); -#endif - -#if MICROPY_QPY_MODULE_ESIM -extern const struct _mp_obj_module_t mp_module_esim; -#endif - -static const mp_rom_map_elem_t mp_module_sim_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_sim) }, - -#if MICROPY_QPY_MODULE_ESIM - { MP_ROM_QSTR(MP_QSTR_esim), MP_ROM_PTR(&mp_module_esim) }, -#endif - - { MP_ROM_QSTR(MP_QSTR_getImsi), MP_ROM_PTR(&qpy_sim_get_imsi_obj) }, - { MP_ROM_QSTR(MP_QSTR_getIccid), MP_ROM_PTR(&qpy_sim_get_iccid_obj) }, - -#ifndef MICROPY_QPY_MODULE_NO_SIMPIN - { MP_ROM_QSTR(MP_QSTR_verifyPin), MP_ROM_PTR(&qpy_sim_verify_pin_obj) }, - { MP_ROM_QSTR(MP_QSTR_changePin), MP_ROM_PTR(&qpy_sim_change_pin_obj) }, - { MP_ROM_QSTR(MP_QSTR_unblockPin), MP_ROM_PTR(&qpy_sim_unblock_pin_obj) }, - - { MP_ROM_QSTR(MP_QSTR_enablePin), MP_ROM_PTR(&qpy_sim_enable_pin_obj) }, - { MP_ROM_QSTR(MP_QSTR_disablePin), MP_ROM_PTR(&qpy_sim_disable_pin_obj) }, -#endif - - { MP_ROM_QSTR(MP_QSTR_getStatus), MP_ROM_PTR(&qpy_sim_get_card_status_obj)}, -#if MICROPY_QPY_MODULE_PHB - { MP_ROM_QSTR(MP_QSTR_getPhonebookStatus), MP_ROM_PTR(&qpy_sim_get_phonebookstatus_obj) }, - { MP_ROM_QSTR(MP_QSTR_readPhonebook), MP_ROM_PTR(&qpy_sim_read_phonebook_record_obj) }, - { MP_ROM_QSTR(MP_QSTR_writePhonebook), MP_ROM_PTR(&qpy_sim_write_phonebook_record_obj) }, -#endif -#if defined (PLAT_ASR) - { MP_ROM_QSTR(MP_QSTR_genericAccess), MP_ROM_PTR(&qpy_sim_genericaccess_obj) }, -#endif -#if MICROPY_QPY_MODULE_DUALSIM || MICROPY_QPY_MODULE_DSDS - { MP_ROM_QSTR(MP_QSTR_switchCard), MP_ROM_PTR(&qpy_sim_switch_card_obj) }, - { MP_ROM_QSTR(MP_QSTR_setSwitchcardCallback), MP_ROM_PTR(&qpy_sim_set_switchcard_cb_obj) }, - { MP_ROM_QSTR(MP_QSTR_getCurSimid), MP_ROM_PTR(&qpy_sim_get_current_simid_obj) }, -#if defined(BOARD_EC800MCN_LE_VOLVGL) || defined(BOARD_EC800MCN_LE_CPE) || defined(BOARD_EG810MEU_LA_VOLVGL) - { MP_ROM_QSTR(MP_QSTR_isInsert), MP_ROM_PTR(&qpy_sim_is_insert_obj) }, -#endif -#endif -#if MICROPY_QPY_MODULE_SIMDET - { MP_ROM_QSTR(MP_QSTR_setSimDet), MP_ROM_PTR(&qpy_sim_set_simdet_obj) }, - { MP_ROM_QSTR(MP_QSTR_getSimDet), MP_ROM_PTR(&qpy_sim_get_simdet_obj) }, - { MP_ROM_QSTR(MP_QSTR_setCallback), MP_ROM_PTR(&qpy_sim_add_event_handler_obj) }, -#endif - - { MP_ROM_QSTR(MP_QSTR___qpy_module_deinit__), MP_ROM_PTR(&qpy_module_sim_deinit_obj) }, - -#if !defined (PLAT_RDA) - { MP_ROM_QSTR(MP_QSTR_getPhoneNumber), MP_ROM_PTR(&qpy_sim_get_phonenumber_obj)}, -#endif -#if MICROPY_QPY_MODULE_PIN_REMATTEMPTS - { MP_ROM_QSTR(MP_QSTR_getPinRemAttempts), MP_ROM_PTR(&qpy_sim_pin_remain_attempts_obj) }, -#endif -#if MICROPY_QPY_MODULE_ESIM_SIM_SWITCH - { MP_ROM_QSTR(MP_QSTR_eSimGetList), MP_ROM_PTR(&qpy_sim_get_esim_list_obj) }, - { MP_ROM_QSTR(MP_QSTR_eSimGetEid), MP_ROM_PTR(&qpy_sim_get_esim_eid_obj) }, - { MP_ROM_QSTR(MP_QSTR_eSimSwitch), MP_ROM_PTR(&qpy_sim_enable_esim_obj) }, -#endif -}; -static MP_DEFINE_CONST_DICT(mp_module_sim_globals, mp_module_sim_globals_table); - - -const mp_obj_module_t mp_module_sim = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t *)&mp_module_sim_globals, -}; - -MP_REGISTER_MODULE(MP_QSTR_sim, mp_module_sim); -#endif - - diff --git a/ports/quectel/modsim.h b/ports/quectel/modsim.h deleted file mode 100644 index ecd199080932e..0000000000000 --- a/ports/quectel/modsim.h +++ /dev/null @@ -1,222 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020-2021 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 __MODSIM_H__ -#define __MODSIM_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#define QL_SIM_MCC_LEN 4 /** Length of the MCC. */ -#define QL_SIM_MNC_MAX 4 /** Maximum length of the MNC. */ -#define QL_SIM_PLMN_NUM_MAX 24 /** Maximum number of PLMN data sets. */ - -typedef enum -{ - QL_SIM_SUCCESS, - QL_SIM_GENERIC_FAILURE, -}QL_SIM_ERROR_CODE; - - - -typedef struct -{ - uint8_t mcc[QL_SIM_MCC_LEN]; /**< MCC value in ASCII characters.*/ - uint8_t mnc[QL_SIM_MNC_MAX]; /**< MNC value in ASCII characters.*/ -}QL_SIM_PLMN_INFO; - -typedef struct -{ - unsigned int preferred_operator_list_num; /**< Must be set to the number of elements in preferred_operator_list. */ - QL_SIM_PLMN_INFO preferred_operator_list[QL_SIM_PLMN_NUM_MAX]; /**< Preferred operator list. */ -}QL_SIM_PREFERRED_OPERATOR_LIST; /* Message */ - -#define QL_SIM_PIN_LEN_MAX 16 /** Maximum length of PIN data. */ -typedef struct -{ - uint8_t pin_value[QL_SIM_PIN_LEN_MAX]; /* Value of the PIN */ -}QL_SIM_VERIFY_PIN_INFO; - -typedef struct -{ - uint8_t old_pin_value[QL_SIM_PIN_LEN_MAX]; /**< Value of the old PIN as a sequence of ASCII characters. */ - uint8_t new_pin_value[QL_SIM_PIN_LEN_MAX]; /**< Value of the new PIN as a sequence of ASCII characters. */ -}QL_SIM_CHANGE_PIN_INFO; - -typedef struct -{ - uint8_t puk_value[QL_SIM_PIN_LEN_MAX]; /**< Value of the PUK as a sequence of ASCII characters. */ - uint8_t new_pin_value[QL_SIM_PIN_LEN_MAX]; /**< Value of the new PIN as a sequence of ASCII characters. */ -}QL_SIM_UNBLOCK_PIN_INFO; - -typedef enum -{ - QL_SIM_CARD_TYPE_UNKNOWN = 0, /**< Unidentified card type. */ - QL_SIM_CARD_TYPE_ICC = 1, /**< Card of SIM or RUIM type. */ - QL_SIM_CARD_TYPE_UICC = 2, /**< Card of USIM or CSIM type. */ -}QL_SIM_CARD_TYPE; - -typedef enum -{ - QL_SIM_STATUS_NOT_INSERTED, - QL_SIM_STATUS_READY, - QL_SIM_STATUS_SIM_PIN, - QL_SIM_STATUS_SIM_PUK, - QL_SIM_STATUS_PH_SIM_LOCK_PIN, - QL_SIM_STATUS_PH_SIM_LOCK_PUK, - QL_SIM_STATUS_PH_FSIM_PIN, - QL_SIM_STATUS_PH_FSIM_PUK, - QL_SIM_STATUS_SIM_PIN2, - QL_SIM_STATUS_SIM_PUK2, - QL_SIM_STATUS_PH_NET_PIN, - QL_SIM_STATUS_PH_NET_PUK, - QL_SIM_STATUS_PH_NET_SUB_PIN, - QL_SIM_STATUS_PH_NET_SUB_PUK, - QL_SIM_STATUS_PH_SP_PIN, - QL_SIM_STATUS_PH_SP_PUK, - QL_SIM_STATUS_PH_CORP_PIN, - QL_SIM_STATUS_PH_CORP_PUK, - QL_SIM_STATUS_BUSY, - QL_SIM_STATUS_BLOCKED, - QL_SIM_STATUS_UNKNOWN -}QL_SIM_STATUS; /**< Card state. */ - -typedef struct -{ - uint8_t pin1_num_retries; /**< Number of PIN 1 retries. */ - uint8_t puk1_num_retries; /**< Number of PUK 1 retries. */ - uint8_t pin2_num_retries; /**< Number of PIN 2 retries. */ - uint8_t puk2_num_retries; /**< Number of PUK 2 retries. */ -}QL_SIM_CARD_PIN_INFO; - - - -typedef struct -{ - QL_SIM_CARD_TYPE card_type; // SIM card type - QL_SIM_STATUS card_state; //SIM card state - QL_SIM_CARD_PIN_INFO card_pin_info; // PIN info -}QL_SIM_CARD_INFO; - -typedef enum -{ - QL_SIM_FILE_TYPE_UNKNOWN = 0, /**< Unknown file type */ - QL_SIM_FILE_TYPE_TRANSPARENT = 1, /**< File structure consisting of a sequence of bytes. */ - QL_SIM_FILE_TYPE_CYCLIC = 2, /**< File structure consisting of a sequence of records, each containing the same fixed size in - chronological order. Once all the records have been used, the oldest data is overwritten. */ - QL_SIM_FILE_TYPE_LINEAR_FIXED = 3, /**< File structure consisting of a sequence of records, each containing the same fixed size. */ -}QL_SIM_FILE_TYPE; - -typedef enum -{ - QL_SIM_FILE_ACCESS_TYPE_ALWAYS =0, - QL_SIM_FILE_ACCESS_TYPE_CHV1 =1, - QL_SIM_FILE_ACCESS_TYPE_CHV2 =2, - QL_SIM_FILE_ACCESS_TYPE_ADM =3, -}QL_SIM_FILE_ACCESS_TYPE; - -typedef struct -{ - QL_SIM_FILE_ACCESS_TYPE read_access; - QL_SIM_FILE_ACCESS_TYPE update_access; -}QL_SIM_FILE_ACCESS_INFO; - -typedef enum -{ - QL_SIM_FILE_STATUS_INVALID =0, - QL_SIM_FILE_STATUS_EFFECTIVE =1, -}QL_SIM_FILE_STATUS; - - -typedef struct -{ - unsigned int id; - QL_SIM_FILE_TYPE type; /**< File type: */ - QL_SIM_FILE_ACCESS_INFO access; /**< File access conditions: */ - QL_SIM_FILE_STATUS status; /**< File status: */ - unsigned int size; /**< Size of transparent files.*/ - unsigned int record_len; /**< Size of each cyclic or linear fixed file record.*/ - unsigned int record_count; /**< Number of cyclic or linear fixed file records.*/ -}QL_SIM_FILE_INFO; - -typedef struct -{ - int sw1; - int sw2; -}QL_SIM_FILE_OPERATION_RET; - -#define QL_SIM_DATA_LEN_MAX 255 -typedef struct -{ - unsigned int data_len; /**< Must be set to the number of elements in data. */ - uint8_t data[QL_SIM_DATA_LEN_MAX]; /**< Data retrieved from the card. */ -}QL_SIM_CARD_FILE_DATA; - -typedef enum -{ - QL_SIM_PHONE_BOOK_STORAGE_DC, /**< 0 - ME dialed calls list */ - QL_SIM_PHONE_BOOK_STORAGE_EN, /**< 1 - SIM (or ME) emergency number */ - QL_SIM_PHONE_BOOK_STORAGE_FD, /**< 2 - SIM fix dialing-phone book */ - QL_SIM_PHONE_BOOK_STORAGE_LD, /**< 3 - SIM last-dialing-phone book */ - QL_SIM_PHONE_BOOK_STORAGE_MC, /**< 4 - ME missed (unanswered) calls list */ - QL_SIM_PHONE_BOOK_STORAGE_ME, /**< 5 - Mobile equipment phonebook */ - QL_SIM_PHONE_BOOK_STORAGE_MT, /**< 6 - */ - QL_SIM_PHONE_BOOK_STORAGE_ON, /**< 7 - SIM own numbers (MSISDNs) list */ - QL_SIM_PHONE_BOOK_STORAGE_RC, /**< 8 - ME received calls list */ - QL_SIM_PHONE_BOOK_STORAGE_SM, /**< 9 - SIM phonebook */ - QL_SIM_PHONE_BOOK_STORAGE_AP, /**< 10 - */ - QL_SIM_PHONE_BOOK_STORAGE_MBDN, /**< 11 - */ - QL_SIM_PHONE_BOOK_STORAGE_MN, /**< 12 - */ - QL_SIM_PHONE_BOOK_STORAGE_SDN, /**< 13 - */ - QL_SIM_PHONE_BOOK_STORAGE_ICI, /**< 14 - */ - QL_SIM_PHONE_BOOK_STORAGE_OCI, /**< 15 - */ -}QL_SIM_PHONE_BOOK_STORAGE; - -#define QL_SIM_PHONE_BOOK_RECORDS_MAX_COUNT 20 - -typedef struct -{ // when write, if phonenum is empty, it means to delete this item specified by index - int index; // the record index in phone book - uint8_t username[32]; // username - uint8_t phonenum[24]; // Phone number, it can include '+'*/ -}QL_SIM_PHONE_BOOK_RECORD_INFO; - - -typedef struct -{ - int record_count; //the count of record - QL_SIM_PHONE_BOOK_RECORD_INFO record[QL_SIM_PHONE_BOOK_RECORDS_MAX_COUNT]; // the list of record -}QL_SIM_PHONE_BOOK_RECORDS_INFO; - - - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/ports/quectel/modsocket.c b/ports/quectel/modsocket.c deleted file mode 100644 index 96921d480425e..0000000000000 --- a/ports/quectel/modsocket.c +++ /dev/null @@ -1,1280 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020-2021 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 -#include "mpconfigport.h" - -#if MICROPY_QPY_MODULE_USOCKET -#include "mpconfigboard.h" - -#include "py/runtime0.h" -#include "py/nlr.h" -#include "py/objlist.h" -#include "py/objstr.h" -#include "py/runtime.h" -#include "py/mperrno.h" -#include "py/mphal.h" -#include "py/stream.h" -#include "py/mperrno.h" -#include "shared/netutils/netutils.h" - -#if defined(PLAT_SONY_ALT1350) -#include "sockets.h" -#include "netdb.h" -#include "ip4.h" -#include "igmp.h" -#include "ip_addr.h" -#include "errno.h" - -#else -#include "lwip/sockets.h" -#include "lwip/netdb.h" -#include "lwip/ip4.h" -#include "lwip/igmp.h" -#endif - -#include "helios_datacall.h" - -#define SOCKET_POLL_US (100000) -#define MDNS_QUERY_TIMEOUT_MS (5000) -#define MDNS_LOCAL_SUFFIX ".local" -#define TIMEOUT_MAX (0xFFFFFFFF) - - -enum { - SOCKET_STATE_NEW, - SOCKET_STATE_CONNECTED, - SOCKET_STATE_PEER_CLOSED, -}; - -typedef struct _socket_obj_t { - mp_obj_base_t base; - int fd; - int timeout; - uint8_t domain; - uint8_t type; - uint8_t proto; - uint8_t state; - unsigned int retries; - #if MICROPY_PY_USOCKET_EVENTS - mp_obj_t events_callback; - struct _socket_obj_t *events_next; - #endif -} socket_obj_t; - -void _socket_settimeout(socket_obj_t *sock, uint64_t timeout_ms); - -#if MICROPY_PY_USOCKET_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; - -void usocket_events_deinit(void) { - usocket_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; -} - -// 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) { - if (*s == sock) { - *s = (*s)->events_next; - return; - } - } -} - -// Polls all registered sockets for readability and calls their callback if they are readable -void usocket_events_handler(void) { - if (usocket_events_head == NULL) { - return; - } - if (--usocket_events_divisor) { - return; - } - usocket_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) { - FD_SET(s->fd, &rfds); - max_fd = MAX(max_fd, s->fd); - } - - // Poll the sockets - struct timeval timeout = { .tv_sec = 0, .tv_usec = 0 }; - int r = select(max_fd + 1, &rfds, NULL, NULL, &timeout); - if (r <= 0) { - return; - } - - // Call the callbacks - for (socket_obj_t *s = usocket_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 - -static inline void check_for_exceptions(void) { - mp_handle_pending(true); -} - -// This function mimics lwip_getaddrinfo, with added support for mDNS queries -static int _socket_getaddrinfo3(const char *nodename, const char *servname, - const struct addrinfo *hints, struct addrinfo **res) { - -#if defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) - int pdp = 1;//Helios_DataCall_GetCurrentPDP(); - return getaddrinfowithcid(nodename, servname, hints, res, pdp); - -#elif defined(PLAT_SONY_ALT1350) - return lwip_getaddrinfo(nodename, servname, hints, res, NULL); -#else - int pdp = Helios_DataCall_GetCurrentPDP(); - - // Normal query - return getaddrinfo_with_pcid(nodename, servname, hints, res, pdp); -#endif -} -extern void mp_hal_stdout_tx_str(const char *str); -static int _socket_getaddrinfo2(const mp_obj_t host, const mp_obj_t portx, struct addrinfo **resp) { -#if defined(PLAT_SONY_ALT1350) - const struct addrinfo hints = { - .ai_family = AF_INET, - .ai_socktype = SOCK_DGRAM, - .ai_protocol = IPPROTO_UDP, - }; -#else - const struct addrinfo hints = { - .ai_family = AF_UNSPEC,//AF_INET, - .ai_socktype = SOCK_STREAM, - }; -#endif - - mp_obj_t port = portx; - if (mp_obj_is_small_int(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); - } - const char *host_str = mp_obj_str_get_str(host); - const char *port_str = mp_obj_str_get_str(port); - - if (host_str[0] == '\0') { - // a host of "" is equivalent to the default/all-local IP address - host_str = "0.0.0.0"; - } - - MP_THREAD_GIL_EXIT(); - int res = _socket_getaddrinfo3(host_str, port_str, &hints, resp); - MP_THREAD_GIL_ENTER(); - - // Per docs: instead of raising gaierror getaddrinfo raises negative error number - if (res != 0) { - mp_raise_OSError(res > 0 ? -res : res); - } - // Somehow LwIP returns a resolution of 0.0.0.0 for failed lookups, traced it as far back - // as netconn_gethostbyname_addrtype returning OK instead of error. - if (*resp == NULL || - (strcmp(resp[0]->ai_canonname, "0.0.0.0") == 0 && strcmp(host_str, "0.0.0.0") != 0)) { - mp_raise_OSError(-2); // name or service not known - } - - return res; -} - -static void _socket_getaddrinfo(const mp_obj_t addrtuple, struct addrinfo **resp) { - mp_obj_t *elem; - mp_obj_get_array_fixed_n(addrtuple, 2, &elem); - _socket_getaddrinfo2(elem[0], elem[1], resp); -} - -static mp_obj_t socket_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, 0, 3, false); - - //socket_obj_t *sock = mp_obj_malloc_with_finaliser(socket_obj_t, usocket_events_head); - socket_obj_t *sock = (socket_obj_t *) m_malloc_with_finaliser(sizeof(socket_obj_t)); - sock->base.type = type_in; - sock->domain = AF_INET; - sock->type = SOCK_STREAM; - sock->proto = 0; - if (n_args > 0) { - sock->domain = mp_obj_get_int(args[0]); - if (n_args > 1) { - sock->type = mp_obj_get_int(args[1]); - if (n_args > 2) { - sock->proto = mp_obj_get_int(args[2]); - } - } - } - - sock->state = sock->type == SOCK_STREAM ? SOCKET_STATE_NEW : SOCKET_STATE_CONNECTED; - - sock->fd = lwip_socket(sock->domain, sock->type, sock->proto); - if (sock->fd < 0) { -#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) - int socket_errno = lwip_get_soc_errno(); -#elif defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) - int socket_errno = EINVAL; -#else - int socket_errno = errno; -#endif - mp_raise_OSError(socket_errno); - } - -#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) - if ((sock->proto != 7) && (sock->proto != 8)) - { - Helios_DataCallInfoStruct info = {0}; - int ret = 0, pid = 0; - for (pid=1; pid<5; pid++) - { - ret = Helios_DataCall_GetInfo(pid, 0, &info); - if (ret == 0) - { - if ((info.v4.state == 1) || (info.v6.state == 1)) - { - break; - } - } - } - - if (ret != 0) - { - mp_raise_OSError(-1); - } - - if (sock->domain == AF_INET) - { - struct sockaddr_in server_addr; - memset(&server_addr, 0, sizeof(server_addr)); - - char ip4_ip_addr[16] = {0}; - inet_ntop(AF_INET, &info.v4.addr.ip, ip4_ip_addr, sizeof(ip4_ip_addr)); - inet_pton(AF_INET, ip4_ip_addr, &server_addr.sin_addr.s_addr); - - server_addr.sin_family = AF_INET; - server_addr.sin_port = 0; - lwip_bind(sock->fd, (struct sockaddr*)&server_addr, sizeof(struct sockaddr_in)); - } - else if (sock->domain == AF_INET6) - { - struct sockaddr_in6 local_v6; - memset(&local_v6, 0, sizeof(local_v6)); - - char ip6_ip_addr[64] = {0}; - inet_ntop(AF_INET6, &info.v6.addr.ip, ip6_ip_addr, sizeof(ip6_ip_addr)); - inet_pton(AF_INET6, ip6_ip_addr, &local_v6.sin6_addr); - - local_v6.sin6_family = AF_INET6; - local_v6.sin6_port = 0; - lwip_bind(sock->fd, (struct sockaddr *)&local_v6, sizeof(struct sockaddr_in6)); - } - } -#endif - - _socket_settimeout(sock, TIMEOUT_MAX); - - return MP_OBJ_FROM_PTR(sock); -} - -static mp_obj_t socket_bind(const mp_obj_t arg0, const mp_obj_t arg1) { - socket_obj_t *self = MP_OBJ_TO_PTR(arg0); - - mp_obj_t *elem; - mp_obj_get_array_fixed_n(arg1, 2, &elem); - const char *addr_info = mp_obj_str_get_str(elem[0]); - int server_port = mp_obj_get_int(elem[1]); - - Helios_DataCallInfoStruct info = {0}; - if (addr_info[0] == '\0') - { - int ret = 0, pid = 0; - for (pid=1; pid<5; pid++) - { - ret = Helios_DataCall_GetInfo(pid, 0, &info); - if (ret == 0) - { - if ((info.v4.state == 1) || (info.v6.state == 1)) - { - break; - } - } - } - - if (ret != 0) - { - mp_raise_OSError(-1); - } - } - - if (self->domain == AF_INET) - { - struct sockaddr_in server_addr; - memset(&server_addr, 0, sizeof(server_addr)); - server_addr.sin_family = AF_INET; -#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) - server_addr.sin_port = lwip_htons(server_port); -#elif defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) || defined(PLAT_SONY_ALT1350) - server_addr.sin_port = htons(server_port); -#endif - - if (addr_info[0] == '\0') - { - char ip4_ip_addr[16] = {0}; - inet_ntop(AF_INET, &info.v4.addr.ip, ip4_ip_addr, sizeof(ip4_ip_addr)); - inet_pton(AF_INET, ip4_ip_addr, &server_addr.sin_addr.s_addr); - } - else - { - inet_pton(AF_INET, addr_info, &server_addr.sin_addr.s_addr); - } - - lwip_bind(self->fd, (struct sockaddr*)&server_addr, sizeof(struct sockaddr_in)); - } - else if (self->domain == AF_INET6) - { - struct sockaddr_in6 local_v6; - memset(&local_v6, 0, sizeof(local_v6)); - - local_v6.sin6_family = AF_INET6; -#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) - local_v6.sin6_port = lwip_htons(server_port); -#elif defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) || defined(PLAT_SONY_ALT1350) - local_v6.sin6_port = htons(server_port); -#endif - - if (addr_info[0] == '\0') - { - char ip6_ip_addr[64] = {0}; - inet_ntop(AF_INET6, &info.v6.addr.ip, ip6_ip_addr, sizeof(ip6_ip_addr)); - //QPY_SOCKET_LOG("[socket][%s][%d]bind IPV6 datacall info .\r\n", ip6_ip_addr, server_port); - inet_pton(AF_INET6, ip6_ip_addr, &local_v6.sin6_addr); - } - else - { - inet_pton(AF_INET6, addr_info, &local_v6.sin6_addr); - //QPY_SOCKET_LOG("[socket][%s][%d]bind IPV6 addr info .\r\n", addr_info, server_port); - } - - lwip_bind(self->fd, (struct sockaddr *)&local_v6, sizeof(struct sockaddr_in6)); - } - - 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) { - socket_obj_t *self = MP_OBJ_TO_PTR(args[0]); - - int backlog = 0; - if (n_args > 1) { - backlog = mp_obj_get_int(args[1]); - backlog = (backlog < 0) ? 0 : backlog; - } - - self->state = SOCKET_STATE_CONNECTED; - int r = lwip_listen(self->fd, backlog); - if (r < 0) { -#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) - int socket_errno = lwip_get_soc_errno(); -#else - int socket_errno = errno; -#endif - mp_raise_OSError(socket_errno); - } - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_listen_obj, 1, 2, socket_listen); - -static mp_obj_t socket_accept(const mp_obj_t arg0) { - socket_obj_t *self = MP_OBJ_TO_PTR(arg0); - mp_obj_t tuple[3]; - char ip4_addr_buf[16] = {0}; - char ip6_addr_buf[128] = {0}; - int ip4_port = 0; - int ip6_port = 0; - - int new_fd = -1; - for (unsigned int i = 0; i <= self->retries; i++) - { - if (self->domain == AF_INET) - { -#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) || defined(PLAT_SONY_ALT1350) - struct sockaddr_in addr_v4; - socklen_t addr_v4_len = sizeof(struct sockaddr_in); - - MP_THREAD_GIL_EXIT(); - new_fd = lwip_accept(self->fd, (struct sockaddr *)&addr_v4, &addr_v4_len); - MP_THREAD_GIL_ENTER(); - -#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) - int socket_errno = lwip_get_soc_errno(); -#else - int socket_errno = errno; -#endif - if (socket_errno != EAGAIN) { - mp_raise_OSError(socket_errno); - } - - inet_ntop(AF_INET, &addr_v4.sin_addr, ip4_addr_buf, sizeof(ip4_addr_buf)); - ip4_port = ntohs(addr_v4.sin_port); -#endif - } - else if (self->domain == AF_INET6) - { -#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) || defined(PLAT_SONY_ALT1350) - struct sockaddr_in6 addr_v6; - socklen_t addr_v6_len = sizeof(struct sockaddr_in6); - - MP_THREAD_GIL_EXIT(); - new_fd = lwip_accept(self->fd, (struct sockaddr *)&addr_v6, &addr_v6_len); - MP_THREAD_GIL_ENTER(); - -#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) - int socket_errno = lwip_get_soc_errno(); -#else - int socket_errno = errno; -#endif - if (socket_errno != EAGAIN) { - mp_raise_OSError(socket_errno); - } - - inet_ntop(AF_INET6, &addr_v6.sin6_addr, ip6_addr_buf, sizeof(ip6_addr_buf)); - ip6_port = ntohs(addr_v6.sin6_port); -#endif - } - - if (new_fd >= 0) { - break; - } - - check_for_exceptions(); - } - - if (new_fd < 0) - { - if (self->retries == 0) { - mp_raise_OSError(MP_EAGAIN); - } else { - mp_raise_OSError(MP_ETIMEDOUT); - } - } - - // create new socket object - socket_obj_t *sock = (socket_obj_t *) m_malloc_with_finaliser(sizeof(socket_obj_t)); - sock->base.type = self->base.type; - sock->fd = new_fd; - sock->domain = self->domain; - sock->type = self->type; - sock->proto = self->proto; - sock->state = SOCKET_STATE_CONNECTED; - tuple[0] = MP_OBJ_FROM_PTR(sock); - - if (self->domain == AF_INET) - { - tuple[1] = mp_obj_new_str(ip4_addr_buf, strlen(ip4_addr_buf)); - tuple[2] = mp_obj_new_int(ip4_port); - } - else if (self->domain == AF_INET6) - { - tuple[1] = mp_obj_new_str(ip6_addr_buf, strlen(ip6_addr_buf)); - tuple[2] = mp_obj_new_int(ip6_port); - } - - _socket_settimeout(sock, TIMEOUT_MAX); - return mp_obj_new_tuple(3, tuple); -} -static MP_DEFINE_CONST_FUN_OBJ_1(socket_accept_obj, socket_accept); - -static mp_obj_t socket_connect(const mp_obj_t arg0, const mp_obj_t arg1) { - socket_obj_t *self = MP_OBJ_TO_PTR(arg0); - int r = 0; - - if ((self->type == SOCK_STREAM) && (self->state == SOCKET_STATE_CONNECTED)){ - mp_raise_OSError(114); - } - - self->state = SOCKET_STATE_CONNECTED; - - struct addrinfo *res; - _socket_getaddrinfo(arg1, &res); - - if (self->timeout > 0 && self->timeout < 25) - { - int sock_nbio = 1; - lwip_ioctl(self->fd, FIONBIO, &sock_nbio); - - MP_THREAD_GIL_EXIT(); - r = lwip_connect(self->fd, res->ai_addr, res->ai_addrlen); - MP_THREAD_GIL_ENTER(); -#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) - int socket_errno = lwip_get_soc_errno(); -#else - int socket_errno = errno; -#endif - -#if defined(PLAT_SONY_ALT1350) - if((r == -1) && (socket_errno != 119)) -#else - if((r == -1) && (socket_errno != 115)) -#endif - { - lwip_freeaddrinfo(res); - mp_raise_OSError(socket_errno); - } - - lwip_freeaddrinfo(res); - - struct timeval t; - t.tv_sec = self->timeout; - t.tv_usec = 0; - -#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) - fd_set read_fds, write_fds; - FD_ZERO(&read_fds); - FD_SET(self->fd, &read_fds); - FD_ZERO(&write_fds); - FD_SET(self->fd, &write_fds); - - MP_THREAD_GIL_EXIT(); - r = lwip_select(self->fd + 1, &read_fds, &write_fds, NULL, &t); - MP_THREAD_GIL_ENTER(); - - if(r <= 0) - { - mp_raise_OSError(MP_ETIMEDOUT); - } - - int value; - int len = sizeof(value); - //get so_error to check connect be RST or not - getsockopt(self->fd, SOL_SOCKET, SO_ERROR, &value, (socklen_t *)&len); - if(value == ECONNRESET) - { - mp_raise_OSError(ECONNRESET); - } -#elif defined(PLAT_SONY_ALT1350) - fd_set read_fds, write_fds; - FD_ZERO(&read_fds);FD_ZERO(&write_fds); - FD_SET(self->fd, &read_fds);FD_SET(self->fd, &write_fds); - - MP_THREAD_GIL_EXIT(); - r = lwip_select(self->fd + 1, &read_fds, &write_fds, NULL, &t); - MP_THREAD_GIL_ENTER(); - - if(r <= 0) - { - mp_raise_OSError(MP_ETIMEDOUT); - } - else - { - if (FD_ISSET(self->fd, &read_fds)) - { - char buf[10]; - int bytes = lwip_recvfrom(self->fd, buf, 0, 0, NULL, NULL); - - socket_errno = errno; - if(bytes < 0) - { - mp_raise_OSError(socket_errno); - } - } - } -#else - fd_set read_fds; - FD_ZERO(&read_fds); - FD_SET(self->fd, &read_fds); - - MP_THREAD_GIL_EXIT(); - r = lwip_select(self->fd + 1, &read_fds, NULL, NULL, &t); - MP_THREAD_GIL_ENTER(); - - if(r <= 0) - { - mp_raise_OSError(MP_ETIMEDOUT); - } -#endif - - sock_nbio = 0; - lwip_ioctl(self->fd, FIONBIO, &sock_nbio); - } - else - { - MP_THREAD_GIL_EXIT(); - r = lwip_connect(self->fd, res->ai_addr, res->ai_addrlen); - MP_THREAD_GIL_ENTER(); -#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) - int socket_errno = lwip_get_soc_errno(); -#else - int socket_errno = errno; -#endif - if (r != 0) - { - lwip_freeaddrinfo(res); - mp_raise_OSError(socket_errno); - } - lwip_freeaddrinfo(res); - } - - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_2(socket_connect_obj, socket_connect); - -static mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) { - (void)n_args; // always 4 - socket_obj_t *self = MP_OBJ_TO_PTR(args[0]); - - int opt = mp_obj_get_int(args[2]); - - switch (opt) { - // level: SOL_SOCKET - case SO_REUSEADDR: { - int val = mp_obj_get_int(args[3]); - int ret = lwip_setsockopt(self->fd, SOL_SOCKET, opt, &val, sizeof(int)); - if (ret != 0) { -#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) - int socket_errno = lwip_get_soc_errno(); -#else - int socket_errno = errno; -#endif - mp_raise_OSError(socket_errno); - } - break; - } - - case TCP_KEEPALIVE: { - if (self->type == SOCK_STREAM) - { - int val = mp_obj_get_int(args[3]); - int optval = 1; - int ret = lwip_setsockopt(self->fd, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(int)); - - optval = val*60; - ret = lwip_setsockopt(self->fd, IPPROTO_TCP, TCP_KEEPIDLE, &optval, sizeof(int)); - - optval = 25; - ret = lwip_setsockopt(self->fd, IPPROTO_TCP, TCP_KEEPINTVL, &optval, sizeof(int));//TCP_KEEPINTVL - - optval = 3; - ret = lwip_setsockopt(self->fd, IPPROTO_TCP, TCP_KEEPCNT, &optval, sizeof(int)); - if (ret != 0) { -#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) - int socket_errno = lwip_get_soc_errno(); -#else - int socket_errno = errno; -#endif - mp_raise_OSError(socket_errno); - } - } - break; - } - - #if MICROPY_PY_USOCKET_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); - self->events_callback = MP_OBJ_NULL; - } - } else { - if (self->events_callback == MP_OBJ_NULL) { - usocket_events_add(self); - } - self->events_callback = args[3]; - } - break; - } - #endif - default: - mp_printf(&mp_plat_print, "Warning: lwip.setsockopt() option not implemented\n"); - } - - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_setsockopt); - -void _socket_settimeout(socket_obj_t *sock, uint64_t timeout_ms) { - // Rather than waiting for the entire timeout specified, we wait sock->retries times - // for SOCKET_POLL_US each, checking for a MicroPython interrupt between timeouts. - // with SOCKET_POLL_MS == 100ms, sock->retries allows for timeouts up to 13 years. - // if timeout_ms == UINT64_MAX, wait forever. - sock->retries = (timeout_ms == TIMEOUT_MAX) ? UINT_MAX : timeout_ms * 1000 / SOCKET_POLL_US; - - sock->timeout = timeout_ms/1000; - - struct timeval timeout = { - .tv_sec = 0, - .tv_usec = timeout_ms ? SOCKET_POLL_US : 0 - }; - lwip_setsockopt(sock->fd, SOL_SOCKET, SO_SNDTIMEO, (const void *)&timeout, sizeof(timeout)); - lwip_setsockopt(sock->fd, SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)); - lwip_fcntl(sock->fd, F_SETFL, timeout_ms ? 0 : O_NONBLOCK); -} - -static mp_obj_t socket_settimeout(const mp_obj_t arg0, const mp_obj_t arg1) { - socket_obj_t *self = MP_OBJ_TO_PTR(arg0); - if (arg1 == mp_const_none) { - _socket_settimeout(self, TIMEOUT_MAX); - } else { - #if MICROPY_PY_BUILTINS_FLOAT - _socket_settimeout(self, (uint64_t)(mp_obj_get_float(arg1) * MICROPY_FLOAT_CONST(1000.0))); - #else - _socket_settimeout(self, mp_obj_get_int(arg1) * 1000); - #endif - } - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_2(socket_settimeout_obj, socket_settimeout); - -static mp_obj_t socket_setblocking(const mp_obj_t arg0, const mp_obj_t arg1) { - socket_obj_t *self = MP_OBJ_TO_PTR(arg0); - if (mp_obj_is_true(arg1)) { - _socket_settimeout(self, TIMEOUT_MAX); - } else { - _socket_settimeout(self, 0); - } - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking); - -// XXX this can end up waiting a very long time if the content is dribbled in one character -// at a time, as the timeout resets each time a recvfrom succeeds ... this is probably not -// good behaviour. -static mp_uint_t _socket_read_data(mp_obj_t self_in, void *buf, size_t size, - struct sockaddr *from, socklen_t *from_len, int *errcode) { - socket_obj_t *sock = MP_OBJ_TO_PTR(self_in); - - // A new socket cannot be read from. - if (sock->state == SOCKET_STATE_NEW) { - *errcode = MP_ENOTCONN; - return MP_STREAM_ERROR; - } - - // If the peer closed the connection then the lwIP socket API will only return "0" once - // from lwip_recvfrom and then block on subsequent calls. To emulate POSIX behaviour, - // which continues to return "0" for each call on a closed socket, we set a flag when - // the peer closed the socket. - if (sock->state == SOCKET_STATE_PEER_CLOSED) { - return 0; - } - - unsigned int retries = 0; - if (sock->timeout > 5) - { - retries = ((sock->timeout/5) - 1); - if (!retries) - retries = 1; - } - else - { - retries = sock->retries; - } - - // XXX Would be nicer to use RTC to handle timeouts - for (unsigned int i = 0; i <= retries; ++i) { - // Poll the socket to see if it has waiting data and only release the GIL if it doesn't. - // This ensures higher performance in the case of many small reads, eg for readline. - - if (sock->timeout > 5) - { - unsigned int retries_i = 0; - retries_i = sock->timeout/5; - if (!((retries_i - 1) == retries)) - { - retries = retries_i; - } - } - else - { - retries = sock->retries; - } - - if (sock->timeout > 5) - { - struct timeval timeout = { .tv_sec = 5, .tv_usec = 0 }; - lwip_setsockopt(sock->fd, SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)); - } - - MP_THREAD_GIL_EXIT(); - int r = lwip_recvfrom(sock->fd, buf, size, 0, from, from_len); - MP_THREAD_GIL_ENTER(); - -#if defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) - int socket_errno = lwip_get_soc_errno(); -#elif defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) - int socket_errno = lwip_get_error(sock->fd); -#else - int socket_errno = errno; -#endif - if (r == 0) - { - sock->state = SOCKET_STATE_PEER_CLOSED; - if (socket_errno == ENOTCONN)//recv FIN - { - *errcode = ENOTCONN; - return MP_STREAM_ERROR; - } - } - - if (r >= 0) { - return r; - } - -#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) - int32_t tcpstate = (int32_t)lwip_getTcpState(sock->fd); - if ((tcpstate < 4) && (sock->type == SOCK_STREAM)) - { - if (socket_errno == EWOULDBLOCK) - { - mp_raise_OSError(115); - } - } -#endif - -#if defined(PLAT_EIGEN) - if ((socket_errno != EWOULDBLOCK) && (socket_errno != 62)) -#else - if (socket_errno != EWOULDBLOCK) -#endif - { - *errcode = socket_errno; - return MP_STREAM_ERROR; - } - check_for_exceptions(); - } - - *errcode = sock->retries == 0 ? MP_EWOULDBLOCK : MP_ETIMEDOUT; - return MP_STREAM_ERROR; -} - -mp_obj_t _socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in, - struct sockaddr *from, socklen_t *from_len) { - size_t len = mp_obj_get_int(len_in); - vstr_t vstr; - vstr_init_len(&vstr, len); - - int errcode; - mp_uint_t ret = _socket_read_data(self_in, vstr.buf, len, from, from_len, &errcode); - if (ret == MP_STREAM_ERROR) { - mp_raise_OSError(errcode); - } - - vstr.len = ret; - return mp_obj_new_str_from_vstr(&vstr); -} - -static mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) { - return _socket_recvfrom(self_in, len_in, NULL, NULL); -} -static MP_DEFINE_CONST_FUN_OBJ_2(socket_recv_obj, socket_recv); - -static mp_obj_t socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) { - struct sockaddr from; - socklen_t fromlen = sizeof(from); - - mp_obj_t tuple[2]; - tuple[0] = _socket_recvfrom(self_in, len_in, &from, &fromlen); - - uint8_t *ip = (uint8_t *)&((struct sockaddr_in *)&from)->sin_addr; - mp_uint_t port = lwip_ntohs(((struct sockaddr_in *)&from)->sin_port); - 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); - -int _socket_send(socket_obj_t *sock, const char *data, size_t datalen) { - int sentlen = 0; - for (unsigned int i = 0; i <= sock->retries && sentlen < (int) datalen; i++) { - MP_THREAD_GIL_EXIT(); - int r = lwip_write(sock->fd, data + sentlen, datalen - sentlen); - MP_THREAD_GIL_ENTER(); -#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) - int socket_errno = lwip_get_soc_errno(); -#else - int socket_errno = errno; -#endif - // lwip returns EINPROGRESS when trying to send right after a non-blocking connect - if (r < 0 && socket_errno != EWOULDBLOCK && socket_errno != EINPROGRESS) { - mp_raise_OSError(socket_errno); - //mp_raise_OSError(errno); - } - if (r > 0) { - sentlen += r; - } - check_for_exceptions(); - } - if (sentlen == 0) { - mp_raise_OSError(sock->retries == 0 ? MP_EWOULDBLOCK : MP_ETIMEDOUT); - } - return sentlen; -} - -static mp_obj_t socket_send(const mp_obj_t arg0, const mp_obj_t arg1) { - socket_obj_t *sock = MP_OBJ_TO_PTR(arg0); - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(arg1, &bufinfo, MP_BUFFER_READ); - int r = _socket_send(sock, bufinfo.buf, bufinfo.len); - return mp_obj_new_int(r); -} -static MP_DEFINE_CONST_FUN_OBJ_2(socket_send_obj, socket_send); - -static mp_obj_t socket_sendall(const mp_obj_t arg0, const mp_obj_t arg1) { - // XXX behaviour when nonblocking (see extmod/modlwip.c) - // XXX also timeout behaviour. - socket_obj_t *sock = MP_OBJ_TO_PTR(arg0); - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(arg1, &bufinfo, MP_BUFFER_READ); - int r = _socket_send(sock, bufinfo.buf, bufinfo.len); - if (r < (int) bufinfo.len) { - mp_raise_OSError(MP_ETIMEDOUT); - } - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_2(socket_sendall_obj, socket_sendall); - -static mp_obj_t socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_in) { - socket_obj_t *self = MP_OBJ_TO_PTR(self_in); - - // get the buffer to send - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(data_in, &bufinfo, MP_BUFFER_READ); - - // create the destination address - struct sockaddr_in to; - to.sin_len = sizeof(to); - to.sin_family = AF_INET; - to.sin_port = lwip_htons(netutils_parse_inet_addr(addr_in, (uint8_t *)&to.sin_addr, NETUTILS_BIG)); - - // send the data - for (unsigned int i = 0; i <= self->retries; i++) { - MP_THREAD_GIL_EXIT(); - int ret = lwip_sendto(self->fd, bufinfo.buf, bufinfo.len, 0, (struct sockaddr *)&to, sizeof(to)); - MP_THREAD_GIL_ENTER(); - if (ret > 0) { - return mp_obj_new_int_from_uint(ret); - } -#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) - int socket_errno = lwip_get_soc_errno(); -#else - int socket_errno = errno; -#endif - if (ret == -1 && socket_errno != EWOULDBLOCK) { - mp_raise_OSError(socket_errno); - //mp_raise_OSError(errno); - } - check_for_exceptions(); - } - mp_raise_OSError(MP_ETIMEDOUT); -} -static MP_DEFINE_CONST_FUN_OBJ_3(socket_sendto_obj, socket_sendto); - -static mp_obj_t socket_fileno(const mp_obj_t arg0) { - socket_obj_t *self = MP_OBJ_TO_PTR(arg0); - return mp_obj_new_int(self->fd); -} -static MP_DEFINE_CONST_FUN_OBJ_1(socket_fileno_obj, socket_fileno); - -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); - -static mp_uint_t socket_stream_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { - return _socket_read_data(self_in, buf, size, NULL, NULL, errcode); -} - -static mp_uint_t socket_stream_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { - socket_obj_t *sock = self_in; - for (unsigned int i = 0; i <= sock->retries; i++) { - MP_THREAD_GIL_EXIT(); - int r = lwip_write(sock->fd, buf, size); - MP_THREAD_GIL_ENTER(); - if (r > 0) { - return r; - } -#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) - int socket_errno = lwip_get_soc_errno(); -#else - int socket_errno = errno; -#endif - // lwip returns MP_EINPROGRESS when trying to write right after a non-blocking connect - if (r < 0 && socket_errno != EWOULDBLOCK && socket_errno != EINPROGRESS) { - *errcode = socket_errno; - return MP_STREAM_ERROR; - } - check_for_exceptions(); - } - *errcode = sock->retries == 0 ? MP_EWOULDBLOCK : MP_ETIMEDOUT; - return MP_STREAM_ERROR; -} - -static mp_uint_t socket_stream_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { - socket_obj_t *socket = self_in; - if (request == MP_STREAM_POLL) { - if (socket->fd == -1) { - return MP_STREAM_POLL_NVAL; - } - - fd_set rfds; - FD_ZERO(&rfds); - fd_set wfds; - FD_ZERO(&wfds); - fd_set efds; - FD_ZERO(&efds); - struct timeval timeout = { .tv_sec = 0, .tv_usec = 0 }; - if (arg & MP_STREAM_POLL_RD) { - FD_SET(socket->fd, &rfds); - } - if (arg & MP_STREAM_POLL_WR) { - FD_SET(socket->fd, &wfds); - } - if (arg & MP_STREAM_POLL_HUP) { - FD_SET(socket->fd, &efds); - } - - int r = select((socket->fd) + 1, &rfds, &wfds, &efds, &timeout); - if (r < 0) { - *errcode = MP_EIO; - return MP_STREAM_ERROR; - } - - mp_uint_t ret = 0; - if (FD_ISSET(socket->fd, &rfds)) { - ret |= MP_STREAM_POLL_RD; - } - if (FD_ISSET(socket->fd, &wfds)) { - ret |= MP_STREAM_POLL_WR; - } - if (FD_ISSET(socket->fd, &efds)) { - ret |= MP_STREAM_POLL_HUP; - } - - // New (unconnected) sockets are writable and have HUP set. - if (socket->state == SOCKET_STATE_NEW) { - ret |= (arg & MP_STREAM_POLL_WR) | MP_STREAM_POLL_HUP; - } - - return ret; - } else if (request == MP_STREAM_CLOSE) { - if (socket->fd >= 0) { - #if MICROPY_PY_USOCKET_EVENTS - if (socket->events_callback != MP_OBJ_NULL) { - usocket_events_remove(socket); - socket->events_callback = MP_OBJ_NULL; - } - #endif - int ret = lwip_close(socket->fd); -#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) - int socket_errno = lwip_get_soc_errno(); -#else - int socket_errno = errno; -#endif - if (ret != 0) { - *errcode = errno; - *errcode = socket_errno; - return MP_STREAM_ERROR; - } - socket->fd = -1; - } - return 0; - } - - *errcode = MP_EINVAL; - return MP_STREAM_ERROR; -} - -#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) -static mp_obj_t socket_getstate(const mp_obj_t self_in) -{ - socket_obj_t *self = MP_OBJ_TO_PTR(self_in); - int32_t tcpstate = (int32_t)lwip_getTcpState(self->fd); - return mp_obj_new_int(tcpstate); -} -static MP_DEFINE_CONST_FUN_OBJ_1(socket_getstate_obj, socket_getstate); -#endif - - -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_sendto), MP_ROM_PTR(&socket_sendto_obj) }, - { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&socket_recv_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) }, -#if defined(PLAT_Unisoc) || defined(PLAT_Unisoc_8850) || defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) - { MP_ROM_QSTR(MP_QSTR_getsocketsta), MP_ROM_PTR(&socket_getstate_obj) }, -#endif - { MP_ROM_QSTR(MP_QSTR_fileno), MP_ROM_PTR(&socket_fileno_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); - -static const mp_stream_p_t socket_stream_p = { - .read = socket_stream_read, - .write = socket_stream_write, - .ioctl = socket_stream_ioctl -}; - -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 quec_socket_getaddrinfo(size_t n_args, const mp_obj_t *args) { - // TODO support additional args beyond the first two - - struct addrinfo *res = NULL; - _socket_getaddrinfo2(args[0], args[1], &res); - mp_obj_t ret_list = mp_obj_new_list(0, NULL); - - for (struct addrinfo *resi = res; resi; resi = resi->ai_next) - { - mp_obj_t addrinfo_objs[5] = { - mp_obj_new_int(resi->ai_family), - mp_obj_new_int(resi->ai_socktype), - mp_obj_new_int(resi->ai_protocol), - mp_obj_new_str(resi->ai_canonname, strlen(resi->ai_canonname)), - mp_const_none - }; - - if (resi->ai_family == AF_INET) - { - char buf[16]; - struct sockaddr_in *addr = (struct sockaddr_in *)resi->ai_addr; - // This looks odd, but it's really just a u32_t - ip_addr_t ip4_addr = { .u_addr.ip4.addr = addr->sin_addr.s_addr }; - ipaddr_ntoa_r(&ip4_addr, buf, sizeof(buf)); - mp_obj_t inaddr_objs[2] = { - mp_obj_new_str(buf, strlen(buf)), - mp_obj_new_int(ntohs(addr->sin_port)) - }; - addrinfo_objs[4] = mp_obj_new_tuple(2, inaddr_objs); - } - else if (resi->ai_family == AF_INET6) - { - char ip6_addr_buf[128] = {0}; - struct sockaddr_in6 *addr = (struct sockaddr_in6 *)resi->ai_addr; - inet_ntop(AF_INET6, &addr->sin6_addr, ip6_addr_buf, sizeof(ip6_addr_buf)); - mp_obj_t inaddr_objs[2] = { - mp_obj_new_str(ip6_addr_buf, strlen(ip6_addr_buf)), - mp_obj_new_int(ntohs(addr->sin6_port)) - }; - addrinfo_objs[4] = mp_obj_new_tuple(2, inaddr_objs); - } - - mp_obj_list_append(ret_list, mp_obj_new_tuple(5, addrinfo_objs)); - } - - if (res) { - lwip_freeaddrinfo(res); - } - return ret_list; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(quec_socket_getaddrinfo_obj, 2, 6, quec_socket_getaddrinfo); - -static mp_obj_t quec_socket_initialize() { - static int initialized = 0; - if (!initialized) { - initialized = 1; - } - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_0(quec_socket_initialize_obj, quec_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___init__), MP_ROM_PTR(&quec_socket_initialize_obj) }, - { MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&socket_type) }, - { MP_ROM_QSTR(MP_QSTR_getaddrinfo), MP_ROM_PTR(&quec_socket_getaddrinfo_obj) }, - - { MP_ROM_QSTR(MP_QSTR_AF_INET), MP_ROM_INT(AF_INET) }, - { MP_ROM_QSTR(MP_QSTR_AF_INET6), MP_ROM_INT(AF_INET6) }, - { MP_ROM_QSTR(MP_QSTR_SOCK_STREAM), MP_ROM_INT(SOCK_STREAM) }, - { MP_ROM_QSTR(MP_QSTR_SOCK_DGRAM), MP_ROM_INT(SOCK_DGRAM) }, - { MP_ROM_QSTR(MP_QSTR_SOCK_RAW), MP_ROM_INT(SOCK_RAW) }, - { MP_ROM_QSTR(MP_QSTR_IPPROTO_TCP), MP_ROM_INT(IPPROTO_TCP) }, - { MP_ROM_QSTR(MP_QSTR_IPPROTO_UDP), MP_ROM_INT(IPPROTO_UDP) }, - { MP_ROM_QSTR(MP_QSTR_IPPROTO_TCP_SER), MP_ROM_INT(7) }, - { MP_ROM_QSTR(MP_QSTR_TCP_CUSTOMIZE_PORT), MP_ROM_INT(8) }, - { MP_ROM_QSTR(MP_QSTR_IPPROTO_IP), MP_ROM_INT(IPPROTO_IP) }, - { MP_ROM_QSTR(MP_QSTR_SOL_SOCKET), MP_ROM_INT(SOL_SOCKET) }, - { MP_ROM_QSTR(MP_QSTR_TCP_KEEPALIVE), MP_ROM_INT(TCP_KEEPALIVE) }, - { MP_ROM_QSTR(MP_QSTR_SO_REUSEADDR), MP_ROM_INT(SO_REUSEADDR) }, -}; - -static MP_DEFINE_CONST_DICT(mp_module_socket_globals, mp_module_socket_globals_table); - -const mp_obj_module_t mp_module_usocket = { - .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 -// this will not conflict with the common implementation provided by -// extmod/mod{lwip,usocket}.c. -MP_REGISTER_MODULE(MP_QSTR_usocket, mp_module_usocket); - -#endif //MICROPY_QPY_MODULE_USOCKET diff --git a/ports/quectel/modules/_boot.py b/ports/quectel/modules/_boot.py index 08b55c4f39ae5..2352f9c4f7949 100644 --- a/ports/quectel/modules/_boot.py +++ b/ports/quectel/modules/_boot.py @@ -14,7 +14,6 @@ import uos import ujson -import dial ''' Mark.Zhu - 2022/12/02 @@ -23,90 +22,25 @@ # global datacall_flag datacall_flag = 1 -def _auto_activate_pdpcontext(): - if "datacall_config.json" not in uos.listdir('/usr'): - # raise ValueError("Not found datacall_config.json.") - dial.setAutoConnect(1, 1) - dial.setAsynMode(1) - dial.start(1, 0, '', '', '', 0) - dial.setAsynMode(0) - else: - retval = dial.getPdpRange() - max_profile = retval[1] - - with open("/usr/datacall_config.json", "r", encoding='utf-8') as fd: - try: - datacall_config = ujson.load(fd) - if not isinstance(datacall_config, dict): - raise ValueError("The format of the datacall_config.json is incorrect.") - - for profile_id in range(1, max_profile+1): - value_of_key_profileid = datacall_config.get(str(profile_id), None) - if value_of_key_profileid is not None: - if not isinstance(value_of_key_profileid, dict): - raise ValueError("The format of the datacall_config.json is incorrect.") - value_of_key_autoActivate = value_of_key_profileid.get("autoActivate", 0) - value_of_key_autoConnect = value_of_key_profileid.get("autoConnect", 0) - if value_of_key_autoConnect==1: - dial.setAutoConnect(profile_id, value_of_key_autoConnect) - if value_of_key_autoActivate == 1: - dial.setAsynMode(1) - ret = -1 - repeat_count = 2 - while (ret == -1) and (repeat_count >= 0): - repeat_count -= 1 - ret = dial.start(profile_id, 0, '', '', '', 0) - if ret == -1: - print('Activation of the {} PDP Context failed.'.format(profile_id)) - dial.setAsynMode(0) - else: - pass - except Exception: - raise ValueError("The format of the datacall_config.json is incorrect.") - - -def _check_data_call(): - retval = dial.getPdpRange() - min = retval[0] - max = retval[1] - - for pdp in range(min, max+1): - nw_sta = dial.getInfo(pdp, 2) - if (nw_sta != -1) and (nw_sta[2][0] == 0) and (nw_sta[3][0] == 0): - continue - elif (nw_sta != -1) and ((nw_sta[2][0] == 1) or (nw_sta[3][0] == 1)): - return 1 - return 0 - - def _repl_enable(): global datacall_flag - if "system_config.json" in uos.listdir("/usr/"): - with open("/usr/system_config.json", "r", encoding='utf-8') as fd: + if "system_config.json" in uos.listdir("/"): + with open("/system_config.json", "r", encoding='utf-8') as fd: try: json_data = ujson.load(fd) - repl_flag = json_data.get("replFlag", 0) datacall_flag = json_data.get("datacallFlag", 1) - repl_pswd = json_data.get("replPswd",None) - import misc - if repl_pswd: - misc.replUpdatePassswd(repl_pswd,repl_pswd) - misc.replEnable(repl_flag, repl_pswd) - else: - misc.replEnable(repl_flag) except ValueError: with open("/usr/system_config.json", "w", encoding='utf-8') as fdw: new_json_data = ujson.dumps({"replFlag": 0, "datacallFlag": datacall_flag}) fdw.write(new_json_data) else: - with open("/usr/system_config.json", "w+", encoding='utf-8') as fd: + with open("/system_config.json", "w+", encoding='utf-8') as fd: repl_data = ujson.dumps({"replFlag": 0}) fd.write(repl_data) try: udev = None - bdev = None try: from uos import VfsLfs1 as VfsLfs except Exception: @@ -114,31 +48,21 @@ def _repl_enable(): udev = uos.FlashDevice('customer_fs', 4096) try: - uos.mount(udev, '/usr') + uos.mount(udev, '/') except Exception as e: if 'ENODEV' in str(e): VfsLfs.mkfs(udev) - uos.mount(udev, '/usr') + uos.mount(udev, '/') else: raise ValueError("LFS usr mount fail".format(e)) - - bdev = uos.FlashDevice('customer_backup_fs', 4096) - try: - uos.mount(bdev, '/bak') - except Exception as e: - if 'ENODEV' in str(e): - VfsLfs.mkfs(bdev) - uos.mount(bdev, '/bak') - else: - raise ValueError("LFS bak mount fail".format(e)) + if 'usr' not in uos.listdir(): + uos.mkdir('usr') + if 'bak' not in uos.listdir(): + uos.mkdir('bak') except Exception: - print('error ocurs in boot step.') + print('error occurs in boot step.') finally: _repl_enable() - if datacall_flag == 1: - ret = _check_data_call() - if ret == 0: - _auto_activate_pdpcontext() diff --git a/ports/quectel/modules/app_fota.py b/ports/quectel/modules/app_fota.py deleted file mode 100644 index fac458ac6990f..0000000000000 --- a/ports/quectel/modules/app_fota.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. -# -# 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. - -#!python3 -# -*- coding:utf-8 -*- - -import app_fota_download -import app_fota_updater -from app_fota_mount import AppFotaPkgMount -class new(object): - def __init__(self): - self.app_fota_pkg_mount = AppFotaPkgMount() - self.app_fota_pkg_mount.mount_disk() - def download(self, url, file_name, headers=None): - return app_fota_download.download(url, file_name, headers) - def bulk_download(self, info=[], headers=None): - return app_fota_download.bulk_download(info, headers) - def set_update_flag(self): - app_fota_download.set_update_flag() - def update(self): - return app_fota_updater.update() - \ No newline at end of file diff --git a/ports/quectel/modules/app_fota_download.py b/ports/quectel/modules/app_fota_download.py deleted file mode 100644 index dc57e95462d73..0000000000000 --- a/ports/quectel/modules/app_fota_download.py +++ /dev/null @@ -1,212 +0,0 @@ -# Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. -# -# 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. - -#!python3 -# -*- coding:utf-8 -*- - -import uos -import request -import ujson -import ql_fs -from app_fota_mount import AppFotaPkgMount -app_fota_pkg_mount = AppFotaPkgMount() - -def get_updater_dir(): - return app_fota_pkg_mount.fota_dir + '/usr/.updater' - -def get_download_stat_file(): - return app_fota_pkg_mount.fota_dir + '/usr/.updater/download.stat' - -def get_update_flag_file(): - return app_fota_pkg_mount.fota_dir + '/usr/.updater/update.flag' - -updater_dir = get_updater_dir() -download_stat_file = get_download_stat_file() -update_flag_file = get_update_flag_file() - - -def _get_download_stat_by_file(file_name): - try: - if not ql_fs.path_exists(get_download_stat_file()): - return None - - fp = open(get_download_stat_file(), 'rt') - if not fp: - return None - - fr = fp.read() - fp.close() - if not fr: - return None - - download_stat = ujson.loads(fr) - for item in download_stat: - if item['name'].lower() == file_name.lower(): - return item - return None - except Exception as e: - return None - - -def _get_download_stat(): - try: - if not ql_fs.path_exists(get_download_stat_file()): - return None - - fp = open(get_download_stat_file(), 'rt') - if not fp: - return None - - fr = fp.read() - fp.close() - if not fr: - return None - - download_stat = ujson.loads(fr) - return download_stat - except Exception as e: - print("get download stat error: "+str(e)) - return None - - -def get_download_stat(): - return _get_download_stat() - - -def _fetch(url, fetched_size, headers=None): - if headers is None or not isinstance(headers, dict): - request_headers = {} - else: - request_headers = headers - request_headers['Range'] = 'bytes={}-'.format(fetched_size) - return request.get(url, headers=request_headers) - - -def _update_download_stat(url, file_name, total_size): - need_append_stat = 1 - download_stat = _get_download_stat() - if download_stat: - for item in download_stat: - if item['name'].lower() == file_name.lower(): - item['url'] = url - item['total_size'] = total_size - need_append_stat = 0 - break - else: - download_stat = [] - - if need_append_stat: - single_download_stat = {} - single_download_stat['url'] = url - single_download_stat['name'] = file_name - single_download_stat['total_size'] = total_size - download_stat.append(single_download_stat) - - json_str = ujson.dumps(download_stat) - fp = open(get_download_stat_file(), 'wt') - fp.write(json_str) - fp.close() - - -def update_download_stat(url, file_name, total_size): - _update_download_stat(url, file_name, total_size) - - -def delete_update_file(file_name): - download_stat = _get_download_stat() - if download_stat: - for item in download_stat[:]: - if item['name'].lower() == file_name.lower(): - download_stat.remove(item) - json_str = ujson.dumps(download_stat) - fp = open(get_download_stat_file(), 'wt') - fp.write(json_str) - fp.close() - - -def download(url, file_name, headers=None): - download_file_name = get_updater_dir() + file_name - ql_fs.mkdirs(ql_fs.path_dirname(download_file_name)) - - single_download_stat = _get_download_stat_by_file(file_name) - if single_download_stat: - if not ql_fs.path_exists(download_file_name): - fetched_size = 0 - else: - fetched_size = ql_fs.path_getsize(download_file_name) - - if fetched_size == single_download_stat['total_size']: - return 0 - else: - fetched_size = 0 - - r = _fetch(url, fetched_size, headers) - if r.status_code == 200 or r.status_code == 206: - total_size = -1 - need_refresh_stat_again = 0 - file_open_mode = '' - if not single_download_stat: - total_size = 'unknown' - _update_download_stat(url, file_name, total_size) - file_open_mode = 'wb+' - else: - file_open_mode = 'ab+' - - fp = open(download_file_name, file_open_mode) - content = r.content - - try: - while True: - c = next(content) - length = len(c) - for i in range(0, length, 4096): - fp.write(c[i:i + 4096]) - except StopIteration: - fp.close() - - r.close() - else: - fp.close() - uos.remove(download_file_name) - r.close() - return -1 - - total_size = ql_fs.path_getsize(download_file_name) - _update_download_stat(url, file_name, total_size) - - return 0 - else: - r.close() - return -1 - - -def bulk_download(info=None, headers=None): - if info is None: - info = [] - fail_result = [] - for item in info: - url = item['url'] - file_name = item['file_name'] - if download(url, file_name, headers) == -1: - fail_result.append(item) - if len(fail_result): - return fail_result - return None - - -def set_update_flag(): - ql_fs.mkdirs(ql_fs.path_dirname(get_update_flag_file())) - fp = open(get_update_flag_file(), 'wb') - fp.close() - diff --git a/ports/quectel/modules/app_fota_mount.py b/ports/quectel/modules/app_fota_mount.py deleted file mode 100644 index 3b98052f75a56..0000000000000 --- a/ports/quectel/modules/app_fota_mount.py +++ /dev/null @@ -1,49 +0,0 @@ -import uos - - -class AppFotaPkgMount(object): - __instance = None - __mount_state = False - __can_mount = False - def __new__(cls, *args, **kwargs): - if cls.__instance is None: - cls.__instance = object.__new__(cls, *args, **kwargs) - return cls.__instance - - def __init__(self): - self.__fota_dir = "/fota" - - @property - def mount_state(self): - return self.__mount_state - - @property - def can_mount(self): - return self.__can_mount - - @property - def fota_dir(self): - if not self.can_mount: - return "" - else: - return self.__fota_dir - - def mount_disk(self): - try: - if not self.mount_state: - fota_pkg = uos.VfsTemp("customer_temp_fs") - uos.mount(fota_pkg, self.__fota_dir) - except Exception as e: - self.__mount_state = False - self.__can_mount = False - else: - self.__mount_state = True - self.__can_mount = True - - def umount_disk(self): - if self.mount_state: - uos.umount(self.fota_dir) - self.__mount_state = False - - def get_fota_file_name(self, path): - return self.fota_dir + path \ No newline at end of file diff --git a/ports/quectel/modules/app_fota_updater.py b/ports/quectel/modules/app_fota_updater.py deleted file mode 100644 index 9214090a1b73c..0000000000000 --- a/ports/quectel/modules/app_fota_updater.py +++ /dev/null @@ -1,91 +0,0 @@ -# Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. -# -# 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. - -#!python3 -# -*- coding:utf-8 -*- - -import uos -import ujson -import ql_fs -import checksum -from app_fota_mount import AppFotaPkgMount -app_fota_pkg_mount = AppFotaPkgMount() - -def get_updater_dir(): - return app_fota_pkg_mount.fota_dir+ '/usr/.updater' - -def get_download_stat_file(): - return app_fota_pkg_mount.fota_dir+'/usr/.updater/download.stat' - -def get_update_flag_file(): - return app_fota_pkg_mount.fota_dir+'/usr/.updater/update.flag' - -updater_dir = get_updater_dir() -download_stat_file = get_download_stat_file() -download_stat_file_max_size = 16384 -update_flag_file = get_update_flag_file() - -def _check_update_flag(): - try: - if ql_fs.path_exists(get_update_flag_file()): - return 1 - else: - return 0 - except Exception as e: - return 0 - -def update(): - if _check_update_flag(): - try: - if not ql_fs.path_exists(get_download_stat_file()): - return -1 - - fp = open(get_download_stat_file(), 'rt') - if not fp: - return -1 - - fr = fp.read(download_stat_file_max_size) - fp.close() - if not fr: - return -1 - download_stat = ujson.loads(fr) - print(download_stat) - download_stat_tmp = download_stat[:] - print(download_stat_tmp) - for item in download_stat: - file_name = item['name'] - download_file_name = get_updater_dir() + file_name - if ql_fs.path_exists(download_file_name): - ql_fs.mkdirs(ql_fs.path_dirname(file_name)) - ql_fs.file_copy(file_name, download_file_name) - checksum.update(file_name) - download_stat_tmp.remove(item) - json_str = ujson.dumps(download_stat_tmp) - fp = open(get_download_stat_file(), 'wt') - if not fp: - return -1 - fp.write(json_str) - fp.close() - uos.remove(download_file_name) - uos.remove(get_update_flag_file()) - uos.remove(get_download_stat_file()) - ql_fs.rmdirs(get_updater_dir()) - app_fota_pkg_mount.umount_disk() - return 0 - - except Exception as e: - return -1 - else: - app_fota_pkg_mount.umount_disk() - return -1 \ No newline at end of file diff --git a/ports/quectel/modules/checkNet.py b/ports/quectel/modules/checkNet.py deleted file mode 100644 index b19a69eb8d880..0000000000000 --- a/ports/quectel/modules/checkNet.py +++ /dev/null @@ -1,231 +0,0 @@ -# Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. -# -# 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. - - -''' -jayceon 2020/12/31 -''' - -import sim -import net -import utime -import modem -import dial -import dataCall -# from misc import Power - -class CheckNetwork(): - def __init__(self, proj_name, proj_version): - self.PROJECT_NAME = proj_name - self.PROJECT_VERSION = proj_version - self.FIRMWARE_VERSION = modem.getDevFwVersion() - # self.POWERON_REASON = Power.powerOnReason() - - def poweron_print_once(self): - sim_sta = sim.getStatus() - print('==================================================') - print('PROJECT_NAME : {}'.format(self.PROJECT_NAME)) - print('PROJECT_VERSION : {}'.format(self.PROJECT_VERSION)) - print('FIRMWARE_VERSION : {}'.format(self.FIRMWARE_VERSION)) - # print('POWERON_REASON : {}'.format(self.POWERON_REASON)) - print('SIM_CARD_STATUS : {}'.format(sim_sta)) - print('==================================================') - - @staticmethod - def check_datacall_status(): - retval = dial.getPdpRange() - min = retval[0] - max = retval[1] - for pdp in range(min, max+1): - datacall_sta = dataCall.getInfo(pdp, 2) - if (datacall_sta != -1) and ((datacall_sta[2][0] == 1) or (datacall_sta[3][0] == 1)): - return 1 - elif (datacall_sta != -1) and (datacall_sta[2][0] == 0) and (datacall_sta[3][0] == 0): - continue - return 0 - - ''' - return format: stagecode, subcode, time - stagecode - - 1:Currently in the stage of getting SIM card state - 2:Currently in the stage of getting network state - 3:Currently in the stage of getting datacall state - subcode - - when stagecode = 1, subcode represents the state of the SIM card - when stagecode = 2, subcode represents the state of the network - when stagecode = 3, subcode represents the state of the datacall - ''' - def wait_network_connected(self, timeout_s=60): - if (timeout_s < 1) or (timeout_s > 3600): - raise OSError("timeout_s should be in [1, 3600]s!") - timeout_ms = timeout_s * 1000 - - ''' - stage_code = 1 - while True: - sim_sta = sim.getStatus() - if sim_sta == 1: - break - elif sim_sta == 0: - return stage_code, sim_sta - elif (sim_sta == 18) or (sim_sta == 20) or (sim_sta == 21): - utime.sleep_ms(100) - timeout_ms -= 100 - if timeout_ms <= 0: - return stage_code, sim_sta - else: - return stage_code, sim_sta - - stage_code = 2 - while True: - net_sta = net.getState() - if net_sta == -1: - utime.sleep_ms(100) - timeout_ms -= 100 - if timeout_ms <= 0: - return stage_code, -1 - else: - if (net_sta[1][0] == 1) or (net_sta[1][0] == 5): - break - else: - utime.sleep_ms(100) - timeout_ms -= 100 - if timeout_ms <= 0: - return stage_code, net_sta[1][0] - - stage_code = 3 - while True: - datacall_sta = self.check_datacall_status() - if datacall_sta == 1: - return stage_code, datacall_sta - else: - utime.sleep_ms(100) - timeout_ms -= 100 - if timeout_ms <= 0: - return stage_code, datacall_sta - ''' - current_time = utime.ticks_ms() - last_time = current_time - stage_code = 1 - while True: - sim_sta = sim.getStatus() - if sim_sta == 1: - break - else: - utime.sleep_ms(100) - current_time = utime.ticks_ms() - timeout_ms -= utime.ticks_diff(current_time, last_time) - last_time = current_time - if timeout_ms <= 0: - return stage_code, sim_sta - - current_time = utime.ticks_ms() - last_time = current_time - stage_code = 2 - while True: - net_sta = net.getState() - if net_sta == -1: - utime.sleep_ms(100) - #timeout_ms -= 100 - current_time = utime.ticks_ms() - timeout_ms -= utime.ticks_diff(current_time, last_time) - last_time = current_time - if timeout_ms <= 0: - return stage_code, -1 - else: - if (net_sta[1][0] == 1) or (net_sta[1][0] == 5): - break - else: - utime.sleep_ms(100) - #timeout_ms -= 100 - current_time = utime.ticks_ms() - timeout_ms -= utime.ticks_diff(current_time, last_time) - last_time = current_time - if timeout_ms <= 0: - return stage_code, net_sta[1][0] - - current_time = utime.ticks_ms() - last_time = current_time - stage_code = 3 - while True: - datacall_sta = self.check_datacall_status() - if datacall_sta == 1: - return stage_code, datacall_sta - else: - utime.sleep_ms(100) - #timeout_ms -= 100 - current_time = utime.ticks_ms() - timeout_ms -= utime.ticks_diff(current_time, last_time) - last_time = current_time - if timeout_ms <= 0: - return stage_code, datacall_sta - - -def wait_network_connected(timeout_s=60): - if (timeout_s < 1) or (timeout_s > 3600): - raise OSError("timeout_s should be in [1, 3600]s!") - timeout_ms = timeout_s * 1000 - - current_time = utime.ticks_ms() - last_time = current_time - stage_code = 1 - while True: - sim_sta = sim.getStatus() - if sim_sta == 1: - break - else: - utime.sleep_ms(100) - current_time = utime.ticks_ms() - timeout_ms -= utime.ticks_diff(current_time, last_time) - last_time = current_time - if timeout_ms <= 0: - return stage_code, sim_sta - - current_time = utime.ticks_ms() - last_time = current_time - stage_code = 2 - while True: - net_sta = net.getState() - if net_sta == -1: - utime.sleep_ms(100) - current_time = utime.ticks_ms() - timeout_ms -= utime.ticks_diff(current_time, last_time) - last_time = current_time - if timeout_ms <= 0: - return stage_code, -1 - else: - if (net_sta[1][0] == 1) or (net_sta[1][0] == 5): - break - else: - utime.sleep_ms(100) - current_time = utime.ticks_ms() - timeout_ms -= utime.ticks_diff(current_time, last_time) - last_time = current_time - if timeout_ms <= 0: - return stage_code, net_sta[1][0] - - current_time = utime.ticks_ms() - last_time = current_time - stage_code = 3 - while True: - datacall_sta = CheckNetwork.check_datacall_status() - if datacall_sta == 1: - return stage_code, datacall_sta - else: - utime.sleep_ms(100) - current_time = utime.ticks_ms() - timeout_ms -= utime.ticks_diff(current_time, last_time) - last_time = current_time - if timeout_ms <= 0: - return stage_code, datacall_sta diff --git a/ports/quectel/modules/checksum.py b/ports/quectel/modules/checksum.py deleted file mode 100644 index 9478cecb26235..0000000000000 --- a/ports/quectel/modules/checksum.py +++ /dev/null @@ -1,157 +0,0 @@ -# Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. -# -# 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. - -# !python3 -# -*- coding:utf-8 -*- - -import ujson -import uos -import file_crc32 -import ql_fs - -checksum_file = '/usr/checksum.json' -checksum_file_max_size = 16384 -backup_checksum_file = '/bak/checksum.json' - - -class _checkError(Exception): - def __init__(self, value): - self.value = value - - def __str__(self): - return repr(self.value) - - -def check(): - if not ql_fs.path_exists(checksum_file): - if not ql_fs.path_exists(backup_checksum_file): - raise _checkError('%s not exist' % checksum_file) - else: - ql_fs.mkdirs(ql_fs.path_dirname(checksum_file)) - ql_fs.file_copy(checksum_file, backup_checksum_file) - - fp = open(checksum_file, 'rt+') - fp.seek(0) - fr = fp.read(checksum_file_max_size) - fp.close() - if not fr: - raise _checkError('%s is empty' % checksum_file) - return fr - - -def retrieve(file_name): - # Pawn 2021-01-14 for JIRA STASR3601-2428 begin - if not file_name.startswith("/"): - file_name = "/" + file_name - # Pawn 2021-01-14 for JIRA STASR3601-2428 end - - json_str = check() - checksum = ujson.loads(json_str) - for item in checksum: - if item['name'].lower() == file_name.lower(): - return item['crc32'] - return None - - -def _flush_checksum(checksum=[], file_name=checksum_file): - json_str = ujson.dumps(checksum) - fp = open(file_name, 'wt+') - fp.seek(0) - wl = fp.write(json_str) - fp.close() - if wl > 0: - return checksum - return None - - -def bak_update(file_name): - # add by Jaxsen xu - checksum = ql_fs.read_json(backup_checksum_file) - - if not file_name.startswith("/"): - file_name = "/" + file_name - - src_file = file_name[file_name.find("/", 1):] - exist_file = False - for item in checksum: - if item['name'].lower() == src_file.lower(): - exist_file = True - file_crc32_value = file_crc32.calc(file_name) - item['crc32'] = file_crc32_value - if not exist_file: - checksum.append(dict(name=src_file.lower(), crc32=file_crc32.calc(file_name))) - return _flush_checksum(checksum, file_name=file_name[:file_name.find("/", 1)] + "/checksum.json") - - -def usr_update(file_name): - try: - data = ql_fs.read_json(checksum_file) - if data is not None: - exist_file = False - for item in data: - if item['name'].lower() == file_name.lower(): - exist_file = True - item['crc32'] = file_crc32.calc(file_name) - if not exist_file: - data.append(dict(name=file_name.lower(), crc32=file_crc32.calc(file_name))) - return ql_fs.touch(checksum_file, data) - return None - except Exception as e: - return None - - -def update(file_name): - try: - json_str = check() - checksum = ujson.loads(json_str) - - # Pawn 2021-01-14 for JIRA STASR3601-2428 begin - if not file_name.startswith("/"): - file_name = "/" + file_name - # Pawn 2021-01-14 for JIRA STASR3601-2428 end - - for item in checksum: - if item['name'].lower() == file_name.lower(): - file_crc32_value = file_crc32.calc(file_name) - if file_crc32_value: - item['crc32'] = file_crc32_value - return _flush_checksum(checksum) - return None - except Exception: - return None - - -def bulk_update(file_name_list=[]): - try: - json_str = check() - checksum = ujson.loads(json_str) - need_update = 0 - - for file_name in file_name_list: - # Pawn 2021-01-14 for JIRA STASR3601-2428 begin - if not file_name.startswith("/"): - file_name = "/" + file_name - # Pawn 2021-01-14 for JIRA STASR3601-2428 end - for item in checksum: - if item['name'].lower() == file_name.lower(): - file_crc32_value = file_crc32.calc(file_name) - if file_crc32_value: - item['crc32'] = file_crc32_value - need_update = 1 - break - if need_update: - return _flush_checksum(checksum) - return None - except Exception: - return None diff --git a/ports/quectel/modules/dataCall.py b/ports/quectel/modules/dataCall.py deleted file mode 100644 index 16ea6c6fa88e8..0000000000000 --- a/ports/quectel/modules/dataCall.py +++ /dev/null @@ -1,284 +0,0 @@ -# -*- coding:utf-8 -*- -# Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. -# -# 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. - - -""" -jayceon 2021/03/23 -""" - -import dial - -def setAutoActivate(profileID, enable,cur_simid=None): - - """ - if profileID < 1 or profileID > 3: - raise ValueError("invalid value, profileID should be in [1,3].") - if enable != 0 and enable != 1: - raise ValueError("invalid value, enable should be 0 or 1.") - if cur_simid != None and cur_simid != 0 and cur_simid != 1: - raise ValueError("invalid value, enable should be 0 or 1.") - - if "datacall_config.json" in uos.listdir('/usr'): - with open("/usr/datacall_config.json", "r", encoding='utf-8') as fd: - try: - datacall_config = ujson.load(fd) - if not isinstance(datacall_config, dict): - raise ValueError("The format of the datacall_config.json is incorrect.") - - value_of_key_profileid = datacall_config.get(str(profileID), None) - if value_of_key_profileid is not None: - if not isinstance(value_of_key_profileid, dict): - raise ValueError("The format of the datacall_config.json is incorrect.") - if cur_simid ==1: - datacall_config[str(profileID)]["autoActivate_1"] = enable - else: - datacall_config[str(profileID)]["autoActivate"] = enable - # value_of_key_autoConnect = value_of_key_profileid.get("autoConnect", 0) - # datacall_config[str(profileID)] = {"autoActivate": enable, "autoConnect": value_of_key_autoConnect} - else: - # datacall_config[str(profileID)] = {"autoActivate": enable, "autoConnect": 0} - if cur_simid ==1: - datacall_config[str(profileID)] = {"autoActivate": 0, "autoConnect": 0,"autoActivate_1": enable} - else: - datacall_config[str(profileID)] = {"autoActivate": enable,"autoConnect": 0} - except Exception: - raise ValueError("The format of the datacall_config.json is incorrect.") - with open("/usr/datacall_config.json", "w", encoding='utf-8') as fd: - datacall_config_json = ujson.dumps(datacall_config) - fd.write(datacall_config_json) - else: - # print('[Warning]The datacall_config.json file does not exist, create it now.') - default_config = { - "1": {"autoActivate": 0, "autoConnect": 0}, - "2": {"autoActivate": 0, "autoConnect": 0}, - "3": {"autoActivate": 0, "autoConnect": 0} - } - if cur_simid ==1: - default_config[str(profileID)]["autoActivate_1"] = enable - else: - default_config[str(profileID)]["autoActivate"] = enable - with open("/usr/datacall_config.json", "w", encoding='utf-8') as fd: - default_config_json = ujson.dumps(default_config) - fd.write(default_config_json) - """ - return -1 - - -def setAutoConnect(profileID, enable, cur_simid=None): - """ - if profileID < 1 or profileID > 3: - raise ValueError("invalid value, profileID should be in [1,3].") - if enable != 0 and enable != 1: - raise ValueError("invalid value, enable should be 0 or 1.") - if cur_simid != None and cur_simid != 0 and cur_simid != 1: - raise ValueError("invalid value, enable should be 0 or 1.") - - if "datacall_config.json" in uos.listdir('/usr'): - with open("/usr/datacall_config.json", "r", encoding='utf-8') as fd: - try: - datacall_config = ujson.load(fd) - if not isinstance(datacall_config, dict): - raise ValueError("The format of the datacall_config.json is incorrect.") - value_of_key_profileid = datacall_config.get(str(profileID), None) - if value_of_key_profileid is not None: - if not isinstance(value_of_key_profileid, dict): - raise ValueError("The format of the datacall_config.json is incorrect.") - if cur_simid ==1: - datacall_config[str(profileID)]["autoConnect_1"] = enable - else: - datacall_config[str(profileID)]["autoConnect"] = enable - else: - if cur_simid ==1: - datacall_config[str(profileID)] = {"autoActivate": 0, "autoConnect": 0,"autoConnect_1": enable} - else: - datacall_config[str(profileID)] = {"autoActivate": 0,"autoConnect": enable} - except Exception: - raise ValueError("The format of the datacall_config.json is incorrect.") - with open("/usr/datacall_config.json", "w", encoding='utf-8') as fd: - datacall_config_json = ujson.dumps(datacall_config) - fd.write(datacall_config_json) - else: - # print('[Warning]The datacall_config.json file does not exist, create it now.') - default_config = { - "1": {"autoActivate": 0, "autoConnect": 0}, - "2": {"autoActivate": 0, "autoConnect": 0}, - "3": {"autoActivate": 0, "autoConnect": 0} - } - if cur_simid ==1: - default_config[str(profileID)]["autoConnect_1"] = enable - else: - default_config[str(profileID)]["autoConnect"] = enable - with open("/usr/datacall_config.json", "w", encoding='utf-8') as fd: - default_config_json = ujson.dumps(default_config) - fd.write(default_config_json) - """ - if cur_simid != None: - dial.setAutoConnect(profileID, enable,cur_simid) - else: - dial.setAutoConnect(profileID, enable) - - - -def setPDPContext(profileID, ipType, apn, username, password, authType, cur_simid=None): - if profileID < 1 or profileID > 3: - raise ValueError("invalid value, profileID should be in [1,3].") - if authType < 0 or authType >3: - raise ValueError("invalid value.") - # Users can set apn, username, and password to None. - # When it is set to None, it means that the original values will not be changed and the original values will be used instead. - if apn is None or username is None or password is None: - pdp_context = dial.getPDPContext(profileID) - if not isinstance(pdp_context,tuple) or len(pdp_context) < 3: - raise ValueError("getPDPContext error.") - if apn is None: - apn = pdp_context[1] - if username is None: - username = pdp_context[2] - if password is None: - password = pdp_context[3] - # if len(username) == 0 and len(password) == 0 and authType != 0: - # authType = 0 - if (len(username) != 0 or len(password) != 0) and authType == 0: - authType = 2 - if cur_simid == None: - return dial.setPDPContext(profileID, ipType, apn, username, password, authType) - else: - return dial.setPDPContext(profileID, ipType, apn, username, password, authType, cur_simid) - - -def getPDPContext(profileID, cur_simid=None): - if profileID < 1 or profileID > 3: - raise ValueError("invalid value, profileID should be in [1,3].") - if cur_simid == None: - return dial.getPDPContext(profileID) - else: - return dial.getPDPContext(profileID, cur_simid) - - - -def setDNSServer(profileID, simID, priDNS, secDNS): - if profileID < 1 or profileID > 3: - raise ValueError("invalid value, profileID should be in [1,3].") - return dial.setDnsserver(profileID, simID, priDNS, secDNS) - - -def activate(profileID, cur_simid=None): - if profileID < 1 or profileID > 3: - raise ValueError("invalid value, profileID should be in [1,3].") - """ - if "datacall_config.json" in uos.listdir('/usr'): - with open("/usr/datacall_config.json", "r", encoding='utf-8') as fd: - try: - datacall_config = ujson.load(fd) - if not isinstance(datacall_config, dict): - raise ValueError("The format of the datacall_config.json is incorrect.") - value_of_key_profileid = datacall_config.get(str(profileID), None) - if value_of_key_profileid is not None: - if not isinstance(value_of_key_profileid, dict): - raise ValueError("The format of the datacall_config.json is incorrect.") - auto_connect = value_of_key_profileid.get("autoConnect", 0) - dial.setAutoConnect(profileID, auto_connect) - else: - raise ValueError("No configuration information for profileID {}.".format(profileID)) - except Exception: - raise ValueError("The format of the datacall_config.json is incorrect.") - """ - if cur_simid == None: - return dial.start(profileID, 0, "", "", "", 0) - else: - return dial.start(profileID, 0, "", "", "", 0,cur_simid) - - -def deactivate(profileID, cur_simid=None): - if profileID < 1 or profileID > 3: - raise ValueError("invalid value, profileID should be in [1,3].") - - pdpctx = dial.getPDPContext(profileID) - if pdpctx != -1: - iptype = pdpctx[0] - if cur_simid == None: - return dial.stop(profileID, iptype) - else: - return dial.stop(profileID, iptype,cur_simid) - else: - return -1 - -###################################################################################### - -def start(profileidx, iptype=0, apn="", username="", password="", authtype=0, cur_simid=None): - ret = dial.setPDPContext(profileidx, iptype, apn, username, password, authtype) - if ret == 0: - if cur_simid == None: - return dial.start(profileidx, iptype, apn, username, password, authtype) - else: - return dial.start(profileidx, iptype, apn, username, password, authtype, cur_simid) - else: - return -1 - - -def stop(profileidx, iptype,cur_simid=None): - if cur_simid == None: - return dial.stop(profileidx, iptype) - else: - return dial.stop(profileidx, iptype, cur_simid) - - -def getInfo(profileidx, iptype, cur_simid=None): - if cur_simid == None: - ret = dial.getInfo(profileidx, iptype) - else: - ret = dial.getInfo(profileidx, iptype, cur_simid) - if ret == -1: - ipv4 = [0, 0, '0.0.0.0', '0.0.0.0', '0.0.0.0'] - ipv6 = [0, 0, '::', '::', '::'] - if iptype ==2: - return (profileidx, iptype, ipv4, ipv6) - elif iptype == 1: - return (profileidx, iptype, ipv6) - elif iptype == 0: - return (profileidx, iptype, ipv4) - return ret - -def getAddressinfo(profileidx, iptype): - ret = dial.getAddressinfo(profileidx, iptype) - if ret == -1: - ipv4 = ['00-00-00-00-00-00', '0.0.0.0', '0.0.0.0'] - ipv6 = ['00-00-00-00-00-00', '::', '::'] - if iptype ==2: - return (ipv4, ipv6) - elif iptype == 1: - return (ipv6) - elif iptype == 0: - return (ipv4) - return ret - -def getSiminfo(simID): - ret = dial.getSiminfo(simID) - if ret == -1: - return (0, 0, 0, 0) - return ret - -def setAsynMode(mode): - return dial.setAsynMode(mode) - -def setCallback(usrfun): - return dial.setCallback(usrfun) - -def setDnsserver(profileidx, simid, new_pri, new_sec): - return dial.setDnsserver(profileidx, simid, new_pri, new_sec) - -def getSpeed(): - return dial.getSpeed() - diff --git a/ports/quectel/modules/file_crc32.py b/ports/quectel/modules/file_crc32.py deleted file mode 100644 index 7e64adc90e152..0000000000000 --- a/ports/quectel/modules/file_crc32.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. -# -# 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. - - -from utils import crc32 - -READ_BLOCK_SIZE = 4096 - -def _check(fp): - fp.seek(0) - fr = fp.read(READ_BLOCK_SIZE) - while fr: - yield fr - fr = fp.read(READ_BLOCK_SIZE) - else: - fp.seek(0) - -def calc(file_name): - csumFunc = crc32() - csum = 0xffffffff - flag = 0 - try: - with open(file_name, 'rb') as fp: - for fr in _check(fp): - csum = csumFunc.update(csum, fr) - flag = 1 - fp.close() - except Exception as e: - pass - finally: - if not flag: - return None - return hex(csum) - diff --git a/ports/quectel/modules/log.py b/ports/quectel/modules/log.py deleted file mode 100644 index 6a64d1fe3998e..0000000000000 --- a/ports/quectel/modules/log.py +++ /dev/null @@ -1,119 +0,0 @@ -# Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. -# -# 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. - -import usys - -CRITICAL = 50 -ERROR = 40 -WARNING = 30 -INFO = 20 -DEBUG = 10 -NOTSET = 0 - -_level_dict = { - CRITICAL: "CRIT", - ERROR: "ERROR", - WARNING: "WARN", - INFO: "INFO", - DEBUG: "DEBUG", -} - -_stream = usys.stderr - -class LogRecord: - def __init__(self): - self.__dict__ = {} - - def __getattr__(self, key): - return self.__dict__[key] - -class Logger: - - level = NOTSET - handlers = [] - record = LogRecord() - - def __init__(self, name): - self.name = name - - def _level_str(self, level): - l = _level_dict.get(level) - if l is not None: - return l - return "LVL%s" % level - - def setLevel(self, level): - self.level = level - - def isEnabledFor(self, level): - return level >= (self.level or _level) - - def log(self, level, msg, *args): - if self.isEnabledFor(level): - level = self._level_str(level) - if args: - msg = msg % args - if self.handlers: - d = self.record.__dict__ - d["levelname"] = level - d["message"] = msg - d["name"] = self.name - for h in self.handlers: - h.emit(self.record) - else: - print(level, ":", self.name, ":", msg, sep="", file=_stream) - - def debug(self, msg, *args): - self.log(DEBUG, msg, *args) - - def info(self, msg, *args): - self.log(INFO, msg, *args) - - def warning(self, msg, *args): - self.log(WARNING, msg, *args) - - def error(self, msg, *args): - self.log(ERROR, msg, *args) - - def critical(self, msg, *args): - self.log(CRITICAL, msg, *args) - - -_level = INFO -_loggers = {} - -def getLogger(name="root"): - if name in _loggers: - return _loggers[name] - l = Logger(name) - _loggers[name] = l - return l - -def set_output(out): - global _stream - from machine import UART - if isinstance(out, UART) or out == usys.stderr or out == usys.stdout: - _stream = out - else: - raise Exception("{} must extend UART".format(out)) - -def basicConfig(level=INFO, filename=None, stream=None, format=None): - global _level, _stream - _level = level - if stream: - _stream = stream - if filename is not None: - print("logging.basicConfig: filename arg is not supported") - if format is not None: - print("logging.basicConfig: format arg is not supported") \ No newline at end of file diff --git a/ports/quectel/modules/modules.py b/ports/quectel/modules/modules.py new file mode 100644 index 0000000000000..9293530d2f221 --- /dev/null +++ b/ports/quectel/modules/modules.py @@ -0,0 +1 @@ +freeze_as_mpy(".", "_boot.py") diff --git a/ports/quectel/modules/ql_fs.py b/ports/quectel/modules/ql_fs.py deleted file mode 100644 index 924cc242fd710..0000000000000 --- a/ports/quectel/modules/ql_fs.py +++ /dev/null @@ -1,137 +0,0 @@ -# Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. -# -# 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. - -#!python3 -# -*- coding:utf-8 -*- - -import uos -import ujson - - -class FileNotFoundError(Exception): - def __init__(self, value): - self.value = value - - def __str__(self): - return repr(self.value) - - -def path_exists(path): - if not path: - return False - else: - try: - if uos.stat(path): - return True - else: - return False - except Exception as e: - return False - - -def file_copy(dstFile, srcFile): - if not path_exists(srcFile): - return False - - dstFp = open(dstFile, 'wb+') - srcFp = open(srcFile, 'rb') - srcFr = srcFp.read(4096) - while srcFr: - dstFp.write(srcFr) - srcFr = srcFp.read(4096) - dstFp.close() - srcFp.close() - return True - - -def path_dirname(path): - if not path: - return '' - - pos = path.rfind('/') - if pos < 0: - return '' - if pos == 0: - return '/' - - dirname = '' - for i in range(0, len(path)): - if i == pos: - break - dirname = dirname + path[i] - return dirname - - -def path_getsize(path): - if path_exists(path): - return uos.stat(path)[-4] - else: - raise FileNotFoundError("can not find: '%s'" % path) - - -def mkdirs(dir): - dir_level_list = dir.split('/') - dir_step_up = dir_level_list[0] - for index in enumerate(dir_level_list): - if dir_step_up and (not path_exists(dir_step_up)): - uos.mkdir(dir_step_up) - if index[0] == (len(dir_level_list) - 1): - break - dir_step_up = dir_step_up + '/' + dir_level_list[index[0] + 1] - - -def rmdirs(dir): - ls = uos.listdir(dir) - if not ls: - uos.remove(dir) - else: - for item in ls: - item = dir + '/' + item - if int(uos.stat(item)[0]) & 0x4000: - rmdirs(item) - else: - uos.remove(item) - rmdirs(dir) - - -def touch(file, data, i=1, file_type="json"): - i = file.find("/", i) - if i != -1: - if not path_exists(file[:i]): - uos.mkdir(file[:i]) - return touch(file, data, i=i + 1, file_type=file_type) - else: - try: - with open(file, "w") as f: - if file_type == "json": - f.write(ujson.dumps(data)) - else: - f.write(data) - except Exception as e: - return -1 - else: - return 0 - - -def write_json(file, data): - return touch(file, data) - - -def read_json(file): - if path_exists(file): - with open(file, "r") as f: - return ujson.load(f) - else: - return None - diff --git a/ports/quectel/modules/queue.py b/ports/quectel/modules/queue.py deleted file mode 100644 index 223bd2e522064..0000000000000 --- a/ports/quectel/modules/queue.py +++ /dev/null @@ -1,51 +0,0 @@ -import _thread - - -class Queue(object): - def __init__(self, maxsize=100): - self.maxsize = maxsize - self.__deque = [] - self.__lock_queue = _thread.allocate_lock() - self.__lock_signal = _thread.allocate_lock() - self.__lock_signal.acquire() - - def put(self, item=None): - self.__lock_queue.acquire() - status = self.__put(item) - self.__lock_queue.release() - if self.__lock_signal.locked(): - self.__lock_signal.release() - return status - - def __pop(self): - self.__lock_queue.acquire() - try: - status = self.__deque.pop(0) - except Exception: - return 0, None - else: - return 1, status - finally: - self.__lock_queue.release() - - def get(self): - if not self.size(): - self.__lock_signal.acquire() - flag, status = self.__pop() - if not flag: - return self.get() - return status - - def __put(self, item): - if self.size() > self.maxsize: - return False - else: - self.__deque.append(item) - return True - - def empty(self): - return not self.size() - - def size(self): - return len(self.__deque) - diff --git a/ports/quectel/modules/request.py b/ports/quectel/modules/request.py deleted file mode 100644 index 208e3c9fbd83a..0000000000000 --- a/ports/quectel/modules/request.py +++ /dev/null @@ -1,470 +0,0 @@ -# Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. -# -# 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. - -import usocket -import ujson -import utime -import uio - -import uos -name, platform = uos.uname()[1].split("=",1) - -if platform != "FCM360W" and platform != "FCM362K": - import net - import dataCall - - -def parse_chunked_data(sock): - data = b'' - while True: - chunk_size_str = b'' - while True: - char = sock.read(1) - if char == b'\r': - continue - if char == b'\n': - break - chunk_size_str += char - chunk_size = int(chunk_size_str, 16) - if chunk_size == 0: - break - chunk_data = sock.read(chunk_size) - data += chunk_data - sock.read(2) # discard \r\n - return data - -class Response: - def __init__(self, f, decode=True, sizeof=4096, flag=False): - self.raw = f - self.encoding = "utf-8" - self.decode = decode - self.sizeof = sizeof - self.read_len = 0 - self.read_data = sizeof - self.flag = flag - - def close(self): - if self.raw: - if s_isopen: - self.raw.close() - self.raw = None - if s_isopen: - if self.raw: - self.raw.close() - - @property - def content(self): - global s_isopen - try: - while True: - if self.read_data > 2048: - block = self.raw.read(2048) - self.read_data -= 2048 - else: - block = self.raw.read(self.read_data) - self.read_len += len(block) - if block: - yield block.decode() if self.decode else block - else: - self.raw.close() - s_isopen = False - break - if (self.flag == True) and (self.sizeof == self.read_len): - self.raw.close() - s_isopen = False - break - except Exception as e: - self.raw.close() # 2021-05-27 - s_isopen = False - if "ETIMEDOUT" in str(e): - raise ValueError(str(e)) - else: - pass - return "" - - @property - def text(self): - for i in self.content: - yield str(i) - return "" - - def json(self): - try: - json_str = "" - for i in self.content: - json_str += i - if json_str: - return ujson.loads(json_str) - else: - return None - except Exception as e: - raise ValueError( - "The data for the response cannot be converted to JSON-type data,please try use response.content method") - - -def request(method, url, data=None, json=None, files=None, stream=None, decode=True, sizeof=2048, timeout=20, headers=None, - ssl_params=None, version=0, files_data=None,files_data_len=None,files_name=None, ipvtype=0,username=None,password=None): - global port - global s_isopen - s_isopen = True - port_exist = False - addr = None - URL = url - if ipvtype == 1 and (url.split("[")[0] == "http://" or url.split("[")[0] == "https://"): - try: - proto, dummy, hosts, path = url.split("/", 3) - except ValueError: - proto, dummy, hosts = url.split("/", 2) - path = "" - - left = hosts.find('[') - if left < 0: - raise ValueError("http missing left delimiter:" + url) - - right = hosts.find(']', left + 1) - if right < 0: - raise ValueError("http missing right delimiter:" + url) - - host = hosts[left + 1:right] - - try: - if hosts[right + 1] == ':': - port = int(hosts[right + 2:]) - port_exist = True - except Exception as e: - pass - - if proto == "http:": - if not port_exist: - port = 80 - elif proto == "https:": - if not port_exist: - port = 443 - else: - raise ValueError("Unsupported protocol: " + proto) - - try: - ai = usocket.getaddrinfo(host, port, 0, usocket.SOCK_STREAM) - except Exception as e: - raise IndexError("Domain name resolution error, please check network connection:" + host) - - import uos - name, platform = uos.uname()[1].split("=",1) - if platform == "FCM360W" or platform == "FCM362K": - raise ValueError("platform Not Support IPV6!") - for i in ai: - if i[0] == 10: - addr = i[-1] - break - host = hosts - - if addr is None: - raise ValueError("Request DNS Parsing IPV6 Fail") - elif not url.split(".")[0].isdigit(): - if not url.startswith("http"): - url = "http://" + url - try: - proto, dummy, host, path = url.split("/", 3) - except ValueError: - proto, dummy, host = url.split("/", 2) - path = "" - if ":" in host: - url_info = host.split(":") - host = url_info[0] - port = int(url_info[1]) - port_exist = True - # jian.yao 2020-12-09 - if proto == "http:": - if not port_exist: - port = 80 - # jian.yao 2020-12-09 - elif proto == "https:": - if not port_exist: - port = 443 - else: - raise ValueError("Unsupported protocol: " + proto) - - try: - ai = usocket.getaddrinfo(host, port, 0, usocket.SOCK_STREAM) - except Exception as e: - raise IndexError("Domain name resolution error, please check network connection") - - if ipvtype == 1: - import uos - name, platform = uos.uname()[1].split("=",1) - if platform == "FCM360W" or platform == "FCM362K": - raise ValueError("platform Not Support IPV6!") - for i in ai: - if i[0] == 10: - addr = i[-1] - break - if addr is None: - raise ValueError("Request DNS Parsing IPV_6 Fail") - else: - for i in ai: - if i[0] == 2: - addr = i[-1] - break - if addr is None: - raise ValueError("Request DNS Parsing IPV_4 Fail") - elif url.split(".")[0].isdigit() and ":" not in url: - raise ValueError( - "MissingSchema: Invalid URL '{}': No schema supplied. Perhaps you meant http://{}? ".format(url, url)) - else: - path = "" - proto = "" - if ":" not in url: - raise ValueError("URL address error: !" + url) - try: - if "/" in url: - ip_info = url.split('/', 1) - path = ip_info[1] - host, port = ip_info[0].split(":") - else: - host, port = url.split(":") - except: - raise ValueError("URL address error: " + url) - try: - ai = usocket.getaddrinfo(host, port, 0, usocket.SOCK_STREAM) - except Exception as e: - raise IndexError("Domain name resolution error, please check network connection") - - if ipvtype == 1: - import uos - name, platform = uos.uname()[1].split("=",1) - if platform == "FCM360W" or platform == "FCM362K": - raise ValueError("platform Not Support IPV6!") - for i in ai: - if i[0] == 10: - addr = i[-1] - break - if addr is None: - raise ValueError("Request DNS Parsing IPV6 Fail") - else: - for i in ai: - if i[0] == 2: - addr = i[-1] - break - if addr is None: - raise ValueError("Request DNS Parsing IPV4 Fail") - #global s - - if ipvtype == 1: - import uos - name, platform = uos.uname()[1].split("=",1) - if platform == "FCM360W" or platform == "FCM362K": - raise ValueError("platform Not Support IPV6!") - try: - s = usocket.socket(usocket.AF_INET6, usocket.SOCK_STREAM, usocket.TCP_CUSTOMIZE_PORT) - except Exception as e: - raise RuntimeError("socket resource malloc FAIL='{}'".format(str(e))) - call_state = dataCall.getInfo(1,1) - if call_state == -1: - raise ValueError("request Connect dataCall get Info FAIL") - elif call_state[2][0] != 1: - raise ValueError("request Connect dataCall get IPV6 Info FAIL") - try: - s.bind((call_state[2][2],0)) - except Exception as e: - raise ValueError("request sock bind IPV6 IP FAIL") - else: - try: - s = usocket.socket(usocket.AF_INET, usocket.SOCK_STREAM) - except Exception as e: - raise RuntimeError("socket resource malloc FAIL='{}'".format(str(e))) - - s.settimeout(timeout) - try: - try: - s.connect(addr) - except Exception as e: - s.close() - raise RuntimeError("HTTP Connection '{}' FAIL='{}'".format(str(e), URL)) - if proto == "https:": - import ussl - try: - if ssl_params: - s = ussl.wrap_socket(s, **ssl_params, server_hostname=host) - else: - s = ussl.wrap_socket(s, server_hostname=host) - except Exception as e: - s.close() - raise RuntimeError("HTTPS USSL '{}' FAIL='{}'".format(str(e), URL)) - if version == 1: - s.write(b"%s /%s HTTP/1.1\r\n" % (method, path)) - else: - s.write(b"%s /%s HTTP/1.0\r\n" % (method, path)) - s.write(b"Host: %s\r\n" % host) - if version == 1: - s.write(b"Connection: close\r\n") - if headers: - if files: - boundary = str(utime.time()) - if not (files.get("filepath") and files.get("filename")): - raise ValueError("Missing key parameters 'filepath' and 'filename'") - if headers.get('Content-Type') == "multipart/form-data": - headers['Content-Type'] = headers['Content-Type'] + '; boundary={}'.format(boundary) - headers['charset'] = 'UTF-8' - if files_data: - boundary = str(utime.time()) - if headers.get('Content-Type') == "multipart/form-data": - headers['Content-Type'] = headers['Content-Type'] + '; boundary={}'.format(boundary) - headers['charset'] = 'UTF-8' - else: - headers = dict() - if files: - boundary = str(utime.time()) - headers['Content-Type'] = "multipart/form-data; boundary={}".format(boundary) - headers['charset'] = 'UTF-8' - if json: - headers['Content-Type'] = "application/json" - for k in headers: - s.write(k) - s.write(b": ") - s.write(headers[k]) - s.write(b"\r\n") - if (username is not None) and (password is not None): - try: - import ubinascii - key = "{}:{}".format(username, password) - key_64 = ubinascii.b2a_base64(key)[:-1].decode('utf-8') - s.write(b"Authorization: Basic {}\r\n".format(key_64)) - except Exception as e: - s.close() - raise RuntimeError("HTTP base64 FAIL='{}'".format(str(e))) - if json is not None: - assert data is None - data = ujson.dumps(json) - if data: - s.write(b"Content-Length: %d\r\n" % len(data)) - s.write(b"\r\n") - s.write(data) - if files_data: - if files_name == None: - raise ValueError("files_name must have") - if files_data_len == None: - raise ValueError("files_data_len must have") - import uos - name,platform = uos .uname()[1].split("=",1) - datas = '--{0}{1}Content-Disposition: form-data; name="file"; filename="{2}"{1}Content-Type: application/octet-stream{1}{1}'.format( - boundary, '\r\n', files_name) - suffix = '{1}--{0}--{1}'.format(boundary, '\r\n') - len_d = files_data_len + len(datas) + len(suffix) - s.write(b"Content-Length: %d\r\n" % len_d) - s.write(b"\r\n") - s.write(datas) - s.write(files_data[0:files_data_len]) - s.write(suffix) - if files: - import uos - counter = 0 - name,platform = uos .uname()[1].split("=",1) - file_path = files.get("filepath") - with open(file_path, 'rb') as f: - content = f.read(4096) - if files.get("name") is not None: - datas = '--{0}{1}Content-Disposition: form-data; {2}{1}{1}{3}{1}--{0}'. \ - format(boundary, '\r\n', files.get("name"), content) - else: - datas = '--{0}{1}Content-Disposition: form-data; name="file"; filename="{2}"{1}Content-Type: application/octet-stream{1}{1}'.format( - boundary, '\r\n', files.get("filename")) - if files.get("filepath1") is not None: - with open('{}'.format(files.get("filepath1")), 'r') as f1: - content1 = f1.read() - if files.get("name1") is not None: - datas += '{1}Content-Disposition: form-data; {2}{1}{1}{3}{1}--{0}'. \ - format(boundary, '\r\n', files.get("name1"), content1) - else: - if files.get("filename1") is None: - raise ValueError("Missing key parameters 'filename1' ") - datas += '{1}Content-Disposition: form-data; name="file"; filename="{2}"{1}Content-Type: application/octet-stream{1}{1}{3}{1}--{0}'. \ - format(boundary, '\r\n', files.get("filename1"), content1) - suffix = '{1}--{0}--{1}'.format(boundary, '\r\n') - len_d = uos.stat(file_path)[-4] + len(datas) + len(suffix) - s.write(b"Content-Length: %d\r\n" % len_d) - s.write(b"\r\n") - s.write(datas) - while content: - s.write(content) - content = f.read(4096) - s.write(suffix) - if not (files and data and files_data): - s.write(b"\r\n") - l = s.readline() - uheaders = {} - chunked_encoding = False - try: - # jian.yao 2020-12-09 Abnormal response handle - l = l.split(None, 2) - status = int(l[1]) - except: - raise ValueError("InvalidSchema: No connection adapters were found for '{}'".format(URL)) - reason = "" - if len(l) > 2: - reason = l[2].rstrip() - con_len = sizeof - con_flag = False - while True: - l = s.readline() - j = l.decode().split(":") - try: - uheaders[j[0]] = j[1].replace("\n", "").replace("\r", "") - except Exception as e: - pass - if not l or l == b"\r\n": - break - - if l.lower().startswith(b"transfer-encoding:"): - if b"chunked" in l.lower(): - chunked_encoding = True - if l.startswith(b'Content-Length:'): - con_len = int(l.split(b' ')[1]) - con_flag = True - #if l.startswith(b"Location:") and not 200 <= status <= 299: - #raise NotImplementedError("Redirects not yet supported") - except OSError: - s.close() - raise - if chunked_encoding: - resp = Response(uio.BytesIO(parse_chunked_data(s)), sizeof=con_len) - else: - resp = Response(s,sizeof=con_len, flag=con_flag) - resp.status_code = status - resp.reason = reason - resp.headers = uheaders - return resp - - -def head(url, **kw): - return request("HEAD", url, **kw) - - -def get(url, **kw): - return request("GET", url, **kw) - - -def post(url, **kw): - return request("POST", url, **kw) - - -def put(url, **kw): - return request("PUT", url, **kw) - - -def patch(url, **kw): - return request("PATCH", url, **kw) - - -def delete(url, **kw): - return request("DELETE", url, **kw) diff --git a/ports/quectel/modules/umqtt.py b/ports/quectel/modules/umqtt.py deleted file mode 100644 index 6daa88dbc133e..0000000000000 --- a/ports/quectel/modules/umqtt.py +++ /dev/null @@ -1,776 +0,0 @@ -# Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. -# -# 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. - - -import uos -name, platform = uos.uname()[1].split("=",1) - -import utime -import log -import _thread -import usocket as socket -import ustruct as struct -import osTimer - -if platform != "FCM360W" and platform != "FCM362K": - import net - import dataCall - -log.basicConfig(level=log.INFO) -mqtt_log = log.getLogger("MQTT") -# bob.xian 2023/9/20 [FCM360W may be a bit unstable when using the log module, so print is temporarily used] begin -if platform == "FCM360W": - mqtt_log.info = print - mqtt_log.warning = print -# bob.xian 2023/9/20 [FCM360W may be a bit unstable when using the log module, so print is temporarily used] end - -#ALIYDEVREGISTER = False -#TOPICLIST = list() -#SERVERACK = set() # PUBACK and SUBACK pids awaiting ACK response -#PING = False - -class MQTTException(Exception): - pass - -def pid_gen(): - pid = 0 - while True: - pid = pid + 1 if pid < 65535 else 1 - yield pid - -class BaseMqtt(object): - CONNECTEXCE = -1 - CONNECTSUCCESS = 0 - ARECONNECT = 1 - SEVCLOSE = 2 - - def __init__(self, client_id, server, port=0, user=None, password=None, keepalive=0, - ssl=False, ssl_params={}, reconn=True, version=4, pingmaxnum=0, manage=False, ipvtype=0): - if port == 0: - port = 8883 if ssl else 1883 - self.client_id = client_id - self.sock = None - self.server = server - self.port = port - self.ssl = ssl - self.ssl_params = ssl_params - self.pid = 0 - self.__newpid = pid_gen() - self.__rcv_pids = set() # PUBACK and SUBACK pids awaiting ACK response - self.cb = None - self.user = user - self.pswd = password - self.keepalive = keepalive - self.lw_topic = None - self.lw_msg = None - self.lw_qos = 0 - self.lw_retain = False - self.last_time = None - self.timerFlag = True - self.pingFlag = False - self.connSta = False - self.reconn = reconn - self.topic_list = [] - self.addr = None - self.qos = 0 - self.mqttversion = version - self.clean_session = True - self.ping_outstanding = False - self.pingmaxnum = pingmaxnum - self.pingnum = 0 - self.mqttlock = None - self.mqttsendlock = None - self.mqttmsglock = None - self.threadId = None - self.__response_time = 5000 - self.wait_flag = 0 - self.ipvtype = ipvtype - self.manage = manage - self.looptask_id = None - self.PING = False - self.SERVERACK = set() # PUBACK and SUBACK pids awaiting ACK response - self.TOPICLIST = list() - self.ALIYDEVREGISTER = False - if keepalive != 0 and keepalive < 5: - raise ValueError("inport parameter error : keepalive >= 5S") - - def _send_str(self, s): - self.sock.write(struct.pack("!H", len(s))) - self.sock.write(s) - - def _recv_len(self): - n = 0 - sh = 0 - while 1: - b = self.sock.read(1)[0] - n |= (b & 0x7f) << sh - if not b & 0x80: - return n - sh += 7 - - def set_callback(self, f): - self.cb = f - - def set_last_will(self, topic, msg, retain=False, qos=0): - assert 0 <= qos <= 2 - assert topic - self.lw_topic = topic - self.lw_msg = msg - self.lw_qos = qos - self.lw_retain = retain - - def connect(self, clean_session=True): - if self.mqttlock is None: - self.mqttlock = _thread.allocate_lock() - if self.mqttsendlock is None: - self.mqttsendlock = _thread.allocate_lock() - if self.mqttmsglock is None: - self.mqttmsglock = _thread.allocate_lock() - j = 1 - while True: - if j > 5: - raise ValueError("DNS Parsing NULL") - try: - addrall = socket.getaddrinfo(self.server, self.port) - except Exception as e: - raise ValueError("DNS Parsing '{}'".format(self.server)) - if not addrall: - j += 1 - utime.sleep_ms(500) - continue - if self.ipvtype == 1: - for i in addrall: - if i[0] == 10: - self.addr = i[-1] - break - if self.addr is None: - raise ValueError("DNS Parsing IPV6 Fail") - else: - try: - self.addr = addrall[0][-1] - except Exception as e: - raise ValueError("DNS Parsing IPV4 Fail") - break - - if self.ipvtype == 1: - if platform == "FCM360W" or platform == "FCM362K": - print("Not Support!") - return - self.sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM, socket.TCP_CUSTOMIZE_PORT) - call_state = dataCall.getInfo(1,1) - if call_state == -1: - raise ValueError("MQTT Connect dataCall get Info FAIL") - elif call_state[2][0] != 1: - raise ValueError("MQTT Connect dataCall get IPV6 Info FAIL") - try: - self.sock.bind((call_state[2][2],0)) - except Exception as e: - raise ValueError("sock bind IPV6 IP FAIL") - else: - self.sock = socket.socket() - self.sock.settimeout(20) - self.sock.connect(self.addr) - if self.ssl: - import ussl - self.sock = ussl.wrap_socket(self.sock, **self.ssl_params, server_hostname = self.server) - - if self.mqttversion == 3: - protocol = b"MQIsdp" - else: - protocol = b"MQTT" - - connect_flags = 0 - connect_flags = clean_session << 1 - remaining_length = 2 + len(protocol) + 1 + 1 + 2 - - if self.client_id: - remaining_length = remaining_length + 2 + len(self.client_id) - if self.user: - remaining_length = remaining_length + 2 + len(self.user) - connect_flags = connect_flags | 0x80 - if self.pswd: - connect_flags = connect_flags | 0x40 - remaining_length = remaining_length + 2 + len(self.pswd) - if self.lw_topic: - connect_flags = connect_flags | 0x04 | ((self.lw_qos & 0x03) << 3) | ((self.lw_retain & 0x01) << 5) - remaining_length += 2 + len(self.lw_topic) + 2 + len(self.lw_msg) - - command = 0x10 - packet = bytearray() - packet.extend(struct.pack("!B", command)) - remaining_bytes = [] - while True: - byte = remaining_length % 128 - remaining_length = remaining_length // 128 - if remaining_length > 0: - byte = byte | 0x80 - - remaining_bytes.append(byte) - packet.extend(struct.pack("!B", byte)) - if remaining_length == 0: - break - - if self.mqttversion == 3: - packet.extend(struct.pack("!H" + str(len(protocol)) + "sBBH", len(protocol), protocol, 3, connect_flags, - self.keepalive)) - else: - packet.extend(struct.pack("!H" + str(len(protocol)) + "sBBH", len(protocol), protocol, 4, connect_flags, - self.keepalive)) - if self.client_id: - packet.extend(struct.pack("!H" + str(len(self.client_id)) + "s", len(self.client_id), self.client_id)) - if self.lw_topic: - packet.extend(struct.pack("!H" + str(len(self.lw_topic)) + "s", len(self.lw_topic), self.lw_topic)) - packet.extend(struct.pack("!H" + str(len(self.lw_msg)) + "s", len(self.lw_msg), self.lw_msg)) - if self.user: - packet.extend(struct.pack("!H" + str(len(self.user)) + "s", len(self.user), self.user)) - if self.pswd: - packet.extend(struct.pack("!H" + str(len(self.pswd)) + "s", len(self.pswd), self.pswd)) - - self.sock.write(packet) - - resp = self.sock.read(4) - self.sock.setblocking(True) - assert resp[0] == 0x20 and resp[1] == 0x02 - if resp[3] != 0: - raise MQTTException(resp[3]) - # self.last_time = utime.mktime(utime.localtime()) - self.last_time = utime.ticks_ms() // 1000 - self.connSta = True - self.clean_session = clean_session - self.PING = False - self.pingnum = self.pingmaxnum - self.ALIYDEVREGISTER = self.sock - return resp[2] & 1 - - def disconnect(self): - # Pawn.zhou 2021/1/12 for JIRA STASR3601-2523 begin - try: - self.timerFlag = False - self.pingFlag = False - self.connSta = False - self.PING = False - self.pingnum = self.pingmaxnum - self.topic = [] - self.sock.write(b"\xe0\0") - # Pawn.zhou 2021/1/12 for JIRA STASR3601-2523 end - except: - mqtt_log.warning("Error send mqtt_dis FAIL.") - try: - if self.mqttsendlock.locked(): - self.mqttsendlock.release() - if self.mqttlock.locked(): - self.mqttlock.release() - if self.mqttmsglock.locked(): - self.mqttmsglock.release() - if self.mqttlock is not None: - _thread.delete_lock(self.mqttlock) - self.mqttlock = None - if self.mqttsendlock is not None: - _thread.delete_lock(self.mqttsendlock) - self.mqttsendlock = None - if self.mqttmsglock is not None: - _thread.delete_lock(self.mqttmsglock) - self.mqttmsglock = None - except: - mqtt_log.warning("Error delete_lock FAIL.") - utime.sleep_ms(500) - try: - self.sock.close() - except: - mqtt_log.warning("Error socket close FAIL.") - - def close(self): - self.sock.close() - - def ping(self): - # self.last_time = utime.mktime(utime.localtime()) - self.last_time = utime.ticks_ms() // 1000 - self.sock.write(b"\xc0\0") - self.PING = True - - def publish(self, topic, msg, retain=False, qos=0): - pkt = bytearray(b"\x30\0\0\0") - pid = next(self.__newpid) - pkt[0] |= qos << 1 | retain - sz = 2 + len(topic) + len(msg) - if qos > 0: - sz += 2 - assert sz < 2097152 - i = 1 - while sz > 0x7f: - pkt[i] = (sz & 0x7f) | 0x80 - sz >>= 7 - i += 1 - pkt[i] = sz - self.sock.write(pkt, i + 1) - self._send_str(topic) - if qos > 0: - self.SERVERACK.add(pid) - struct.pack_into("!H", pkt, 0, pid) - self.sock.write(pkt, 2) - self.sock.write(msg) - # self.last_time = utime.mktime(utime.localtime()) - if qos == 0: - if self.keepalive >= 30: - # time = utime.mktime(utime.localtime()) - time = utime.ticks_ms() // 1000 - if (time - self.last_time) > (self.keepalive - 15): - self.last_time = time - self.keepalive - return True - - if qos == 1: - if self.wait_flag == 0: - self.wait_msg() - if not self._await_pid(pid): - mqtt_log.warning("publish Pid[%s] QOS1 message was not received correctly"%pid) - return False - else: - # self.last_time = utime.mktime(utime.localtime()) - self.last_time = utime.ticks_ms() // 1000 - return True - elif qos == 2: - mqtt_log.warning("publish QOS2 Not Support") - assert 0 - - def __subscribe(self, topic, qos, sock): - if sock: - self.sock = sock - pkt = bytearray(b"\x82\0\0\0") - pid = next(self.__newpid) - self.SERVERACK.add(pid) - struct.pack_into("!BH", pkt, 1, 2 + 2 + len(topic) + 1, pid) - self.sock.write(pkt) - self._send_str(topic) - self.sock.write(qos.to_bytes(1, "little")) - if self.ssl == False: - self.sock.settimeout(5) - while True: - if self.wait_flag == 0: - if self.mqttmsglock.locked(): - return True - op = self.wait_msg() - if op == 0x90: - return True - else: - return False - else: - if not self._await_pid(pid): - return False - else: - return True - - def subscribe(self, topic, qos=0, sock=None): - assert self.cb is not None, "Subscribe callback is not set" - if topic not in self.topic_list: - self.topic_list.append(topic) - self.TOPICLIST = self.topic_list - self.qos = qos - self.__subscribe(topic, qos=qos, sock=sock) - - def publish_ack(self, pid): - pkt = bytearray(b"\x40\x02\0\0") - struct.pack_into("!H", pkt, 2, pid) - while True: - try: - if self.mqttsendlock.locked(): - utime.sleep_ms(10) - continue - self.mqttsendlock.acquire() - self.sock.write(pkt) - self.mqttsendlock.release() - return - except Exception as e: - mqtt_log.warning("Publish Pid[%s] ACK OSError[%s]." %(pid, str(e))) - if self.mqttsendlock.locked(): - self.mqttsendlock.release() - return - - # Wait for a single incoming MQTT message and process it. - # Subscribed messages are delivered to a callback previously - # set by .set_callback() method. Other (internal) MQTT - # messages processed internally. - def wait_msg(self): - global SUBACK - SUBACK = True - if self.ssl: - res = self.sock.read(1) - else: - res = self.sock.recv(1) - self.sock.setblocking(True) - if res is None: - return None - if res == b"": - # raise OSError(-1) - # Pawn 2020/11/14 - WFZT mqttBUg -1 - return None - - if res == b"\xd0": # PINGRESP - self.PING = False - sz = self.sock.read(1)[0] - assert sz == 0 - return res - - if res == b'\x40': # PUBACK: save pid - sz = self.sock.read(1) - if sz != b"\x02": - mqtt_log.warning("Publish message does not return ACK correctly") - return - rcv_pid = self.sock.read(2) - pid = rcv_pid[0] << 8 | rcv_pid[1] - if pid in self.SERVERACK: - self.SERVERACK.discard(pid) - return - else: - return - - sub_ack = res[0] - if (sub_ack & 0xf0) == 0x90: # SUBSCRIBE: - resp = self.sock.read(4) - pid = resp[1] << 8 | resp[2] - if pid in self.SERVERACK: - self.SERVERACK.discard(pid) - if resp[3] == 0x80: - mqtt_log.warning("subscribe topic ACK Fail") - return 0x80 - else: - return 0x90 - - op = res[0] - if op & 0xf0 != 0x30: - return op - sz = self._recv_len() - topic_len = self.sock.read(2) - topic_len = (topic_len[0] << 8) | topic_len[1] - topic = self.sock.read(topic_len) - sz -= topic_len + 2 - if op & 6: - pid = self.sock.read(2) - pid = pid[0] << 8 | pid[1] - sz -= 2 - msg = self.sock.read(sz) - # self.last_time = utime.mktime(utime.localtime()) - if op & 6 == 2: - task_stacksize = _thread.stack_size() - name,platform = uos.uname()[1].split("=",1) - if platform == "EC600E" or platform == "EC800E" or platform == "FCM360W" or platform == "FCM362K": - _thread.stack_size(2*1024) - _thread.start_new_thread(self.publish_ack, (pid,)) - _thread.stack_size(task_stacksize) - if op & 6 == 4: - assert 0 - try: - self.cb(topic, msg) - except Exception as e: - mqtt_log.warning("set_callback OSError[%s]." % str(e)) - - # Checks whether a pending message from server is available. - # If not, returns immediately with None. Otherwise, does - # the same processing as wait_msg. - def check_msg(self): - self.sock.setblocking(False) - return self.wait_msg() - - def _timeout(self, t): - return utime.ticks_diff(utime.ticks_ms(), t) > self.__response_time - - def _await_pid(self, pid): - t = utime.ticks_ms() - while pid in self.SERVERACK: # local copy - if self._timeout(t): - break # Must repub or bail out - utime.sleep_ms(500) - else: - return True # PID received. All done. - return False - - def get_mqttsta(self): - ''' - Get the MQTT connection status - CONNECTEXCE -1:Connect the interrupt - CONNECTSUCCESS 0:connection is successful - ARECONNECT 1:In the connection - SEVCLOSE 2:server closes the connection - ''' - socket_sta = self.sock.getsocketsta() - if socket_sta == 0: - return self.ARECONNECT - elif (socket_sta == 2) or (socket_sta == 3): - return self.ARECONNECT - elif (socket_sta == 4) and self.connSta: - return self.CONNECTSUCCESS - elif (socket_sta == 7) or (socket_sta == 8): - return self.SEVCLOSE - else: - return self.CONNECTEXCE - - -class MQTTClient(BaseMqtt): - DELAY = 2 - DEBUG = False - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.error_callback = None - self.subtimer = osTimer() - - def delay(self, i): - utime.sleep(self.DELAY) - - def disconnect(self): - try: - self.subtimer.stop() - self.subtimer.delete_timer() - except: - pass - super().disconnect() - - def sub_timer_task(self, arg): - if not self.topic_list: - self.topic_list = self.TOPICLIST - for topic_re in self.topic_list: - super().subscribe(topic_re, qos=self.qos, sock=self.ALIYDEVREGISTER) - - def error_register_cb(self, func): - self.error_callback = func - - def base_reconnect(self): - i = 0 - if self.mqttlock.locked(): - return - self.mqttlock.acquire() - if self.looptask_id is not None and self.PING != True: - if self.mqttsendlock.locked(): - self.mqttsendlock.release() - if self.wait_flag == 0: - _thread.stop_thread(self.looptask_id) - self.looptask_id = None - if self.reconn: - if self.error_callback is not None: - e = "reconnect_start" - self.error_callback(e)#start reconnect - while 1: - try: - if not self.timerFlag: - break - #felix.hou 2024.5.11 add ,close() may cause reconnecting to the mqtt server to fail - if platform == "FCM360W" or platform == "FCM362K": - self.sock.shutdown() - utime.sleep_ms(20) - self.sock.close() - else: - self.sock.close() - #felix.hou 2024.5.11 add ,close() may cause reconnecting to the mqtt server to fail - time_info = self.logTime() - mqtt_log.info( - "[%s] The network condition has been restored and an attempt will be made to reconnect" % time_info) - self.pingFlag = False - self.connSta = False - self.connect(self.clean_session) - mqtt_log.info("[%s] Reconnection successful!" % time_info) - if self.manage: - self.subtimer.start(3000, 0, self.sub_timer_task) - else: - if not self.topic_list: - self.topic_list = self.TOPICLIST - for topic_re in self.topic_list: - super().subscribe(topic_re, self.qos) - time_info = self.logTime() - if self.mqttlock.locked(): - self.mqttlock.release() - if self.reconn: - if self.error_callback is not None: - e = "reconnect_success" - try: - self.error_callback(e)#reconnect success - except Exception as e: - mqtt_log.warning("error_callback OSError[%s]." % str(e)) - return - except Exception as e: - if not self.timerFlag: - break - i += 1 - time_info = self.logTime() - mqtt_log.warning( - "[%s] The connection attempt failed [%s] and will be tried again after %d seconds." % (time_info, str(e), 5 + i)) - utime.sleep(5 + i) - if platform != "FCM360W" and platform != "FCM362K": - net_sta = net.getState() - if net_sta != -1 and ((net_sta[1][0] == 1) or (net_sta[1][0] == 5)): - call_state = dataCall.getInfo(1, 0) - if call_state == -1: - mqtt_log.info("LTE datacall Fail.") - elif call_state[2][0] != 1: - mqtt_log.info("LTE datacall IPV4 Fail.") - else: - mqtt_log.info("LTE Net unregistered.") - - def publish(self, topic, msg, retain=False, qos=0): - while True: - try: - if self.mqttsendlock.locked(): - utime.sleep_ms(10) - continue - self.mqttsendlock.acquire() - ret = super().publish(topic, msg, retain, qos) - self.mqttsendlock.release() - return ret - except Exception as e: - mqtt_log.warning("Publish Fail OSError[%s]." % str(e)) - if self.mqttsendlock.locked(): - self.mqttsendlock.release() - return False - - def wait_msg(self): - while True: - try: - # The state changes when disconnect is called - if not self.timerFlag: - break - self.wait_flag = 1 - if self.mqttmsglock.locked(): - utime.sleep_ms(10) - continue - self.mqttmsglock.acquire() - ret = super().wait_msg() - self.mqttmsglock.release() - self.wait_flag = 0 - return ret - except Exception as e: - if self.mqttmsglock is not None and self.mqttmsglock.locked(): - self.mqttmsglock.release() - if not self.timerFlag: - break - if not self.reconn: - raise e - # Whether to use the built-in reconnect mechanism - time_info = self.logTime() - self.wait_flag = 0 - if self.ping == True: - mqtt_log.warning("[%s] wait msg, send ping timeout. Trying to reconnect" % time_info) - else: - mqtt_log.warning("[%s] wait msg OSError[%s] . Trying to reconnect" % (time_info, str(e))) - utime.sleep(1) - self.base_reconnect() - - def connect(self, clean_session=True): - try: - super().connect(clean_session) - except Exception as e: - if str(e) == "104": - raise ValueError( - "MQTT Connect Error='{}' Server Actively RST Disconnected.Need Check addr&port".format(e)) - elif str(e) == "107" or str(e) == "4": - raise ValueError( - "MQTT Connect Error='{}' Server Actively FIN Disconnected.Need Check Connection parameters".format( - e)) - elif str(e) == "110": - raise ValueError("MQTT Connect Error='{}' Timeout.Need Check Network".format(e)) - raise ValueError("MQTT Connect error='{}' FAIL".format(e)) - if self.looptask_id is None: - if self.keepalive > 0 and not self.pingFlag: - # Pawn.zhou 2021/1/12 for JIRA STASR3601-2523 begin - task_stacksize = _thread.stack_size() - name,platform = uos.uname()[1].split("=",1) - if platform == "EC600E" or platform == "EC800E": - _thread.stack_size(8 * 1024) - elif platform == "FCM360W" or platform == "FCM362K": - _thread.stack_size(2 * 1024) - else: - _thread.stack_size(16 * 1024) - self.looptask_id = _thread.start_new_thread(self.__loop_forever, ()) - _thread.stack_size(task_stacksize) - self.pingFlag = True - # Pawn.zhou 2021/1/12 for JIRA STASR3601-2523 end - return 0 - - def __loop_forever(self): - while True: - if self.keepalive >= 5: - keepalive = self.keepalive - 3 - try: - if not self.timerFlag: - if self.mqttsendlock is not None and self.mqttsendlock.locked(): - self.mqttsendlock.release() - self.looptask_id = None - break - # time = utime.mktime(utime.localtime()) - time = utime.ticks_ms() // 1000 - - if time - self.last_time > keepalive: - if self.mqttlock.locked(): - utime.sleep(5) - continue - if self.PING == True: - mqtt_log.warning("[%s] Send ping timeout 2. Trying to reconnect" % time) - if not self.reconn: - if self.mqttsendlock is not None and self.mqttsendlock.locked(): - self.mqttsendlock.release() - self.looptask_id = None - raise Exception("Send ping timeout.") - else: - if self.pingnum <= 0: - mqtt_log.warning("[%s] Send ping timeout 1. Trying to reconnect" % time) - self.sock.settimeout(3) - self.pingFlag = False - if self.mqttsendlock is not None and self.mqttsendlock.locked(): - self.mqttsendlock.release() - self.looptask_id = None - break - else: - mqtt_log.warning("[%s] Trying to resend ping(%d)" % (time, self.pingnum)) - self.pingnum = self.pingnum - 1 - while True: - if self.mqttsendlock is not None and self.mqttsendlock.locked(): - utime.sleep_ms(10) - continue - self.mqttsendlock.acquire() - super().ping() - self.mqttsendlock.release() - utime.sleep(5) - break - else: - utime.sleep(5) - continue - except Exception as e: - if self.mqttsendlock is not None and self.mqttsendlock.locked(): - self.mqttsendlock.release() - if not self.timerFlag: - self.looptask_id = None - break - # Network normal, take the initiative to throw exception - if not self.reconn: - if self.error_callback is not None: - self.error_callback(str(e)) - self.pingFlag = False - self.looptask_id = None - break - else: - self.pingFlag = False - self.looptask_id = None - break - # Whether to use the built-in reconnect mechanism - time_info = self.logTime() - if self.PING == True: - mqtt_log.warning("[%s] Send ping timeout 3. Trying to reconnect" % time_info) - else: - mqtt_log.warning("[%s] Send ping, Network exception. Trying to reconnect" % time_info) - utime.sleep(2) - self.base_reconnect() - break - - def logTime(self): - log_time = utime.localtime() - time_info = "%d-%d-%d %d:%d:%d" % ( - log_time[0], log_time[1], log_time[2], log_time[3], log_time[4], log_time[5],) - return time_info diff --git a/ports/quectel/moduos.c b/ports/quectel/moduos.c index 26d44011c421f..d9641b9895ff4 100644 --- a/ports/quectel/moduos.c +++ b/ports/quectel/moduos.c @@ -122,21 +122,8 @@ static mp_obj_t os_uname(void) { return mp_obj_new_tuple(6, tuple); } - static MP_DEFINE_CONST_FUN_OBJ_0(os_uname_obj, os_uname); -#include "quectel_version.h" -static mp_obj_t os_sdkver(void) { -#if defined(PLAT_Qualcomm) - return mp_obj_new_str(mob_sw_rev, strlen(mob_sw_rev)); -#else - extern mp_obj_t queclib_dev_fw_version(); - return queclib_dev_fw_version(); -#endif -} - -static MP_DEFINE_CONST_FUN_OBJ_0(os_sdkver_obj, os_sdkver); - // 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 OS_URANDOM_SEED_ON_IMPORT (1) @@ -182,7 +169,6 @@ static const mp_rom_map_elem_t os_module_globals_table[] = { #endif { MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&os_uname_obj) }, { MP_ROM_QSTR(MP_QSTR_uname2), MP_ROM_PTR(&os_uname2_obj) }, - { MP_ROM_QSTR(MP_QSTR_sdkver), MP_ROM_PTR(&os_sdkver_obj) }, #if MICROPY_PY_OS_DUPTERM { MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&mp_uos_dupterm_obj) }, { MP_ROM_QSTR(MP_QSTR_dupterm_notify), MP_ROM_PTR(&os_dupterm_notify_obj) }, diff --git a/ports/quectel/modussl_mbedtls.c b/ports/quectel/modussl_mbedtls.c deleted file mode 100644 index 149279d95beff..0000000000000 --- a/ports/quectel/modussl_mbedtls.c +++ /dev/null @@ -1,600 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020-2021 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" -#include "mpconfigport.h" - - -#if MICROPY_PY_USSL && MICROPY_SSL_MBEDTLS -#include "mpconfigboard.h" -#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" -#include "mbedtls/x509.h" -#include "helios_debug.h" - -#define QPY_MPUSSL_LOG(msg, ...) custom_log(Ussl, msg, ##__VA_ARGS__) - -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 ca; - 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; -}; - -extern 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; - QPY_MPUSSL_LOG("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_printf(&mp_plat_print, "[mbedtls](write buf = %s ) :\n", buf); - - mp_uint_t out_sz = sock_stream->write(sock, buf, len, &err); - mp_printf(&mp_plat_print, "[mbedtls](write out_sz = %d ) :\n", out_sz); - 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; - } -} - -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_printf(&mp_plat_print, "[mbedtls](read len = %d ) :\n", len); - - mp_uint_t out_sz = sock_stream->read(sock, buf, len, &err); - - mp_printf(&mp_plat_print, "[mbedtls](read out_sz = %d ) :\n", out_sz); - - if (out_sz == MP_STREAM_ERROR) { - if (mp_is_nonblocking_error(err)) { - return MBEDTLS_ERR_SSL_WANT_READ; - } - return -err; - } else { - return out_sz; - } -} - -#define SSL_IGNORE_BADCERT_EXPIRED 0x01 /**< The certificate validity has expired. */ -#define SSL_IGNORE_BADCERT_REVOKED 0x02 /**< The certificate has been revoked (is on a CRL). */ -#define SSL_IGNORE_BADCERT_CN_MISMATCH 0x04 /**< The certificate Common Name (CN) does not match with the expected CN. */ -#define SSL_IGNORE_BADCERT_NOT_TRUSTED 0x08 /**< The certificate is not correctly signed by the trusted CA. */ -#define SSL_IGNORE_BADCRL_NOT_TRUSTED 0x10 /**< The CRL is not correctly signed by the trusted CA. */ -#define SSL_IGNORE_BADCRL_EXPIRED 0x20 /**< The CRL is expired. */ -#define SSL_IGNORE_BADCERT_MISSING 0x40 /**< Certificate was missing. */ -#define SSL_IGNORE_BADCERT_SKIP_VERIFY 0x80 /**< Certificate verification was skipped. */ -#define SSL_IGNORE_BADCERT_FUTURE 0x0200 /**< The certificate validity starts in the future. */ - -static int my_verify( void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags ) -{ - char buf[1024]; - ((void) data); - - mbedtls_x509_crt_info( buf, sizeof( buf ) - 1, "", crt ); - - mp_printf(&mp_plat_print, "[mbedtls](*flags %d error) :\n", *flags); - if(*flags & (SSL_IGNORE_BADCERT_FUTURE)) - { - *flags &= ~(SSL_IGNORE_BADCERT_FUTURE); - return( 0 ); - } - - return *flags; -} - -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); - mp_obj_ssl_socket_t *o = (mp_obj_ssl_socket_t *) m_malloc_with_finaliser(sizeof(mp_obj_ssl_socket_t)); - #endif - - int ret = -1; - o->entropy = (mbedtls_entropy_context *)malloc(sizeof(mbedtls_entropy_context)); - if (o->entropy == NULL){ - goto cleanup; - } - o->ctr_drbg = (mbedtls_ctr_drbg_context *)malloc(sizeof(mbedtls_ctr_drbg_context)); - if (o->ctr_drbg == NULL){ - goto cleanup; - } - o->ssl = (mbedtls_ssl_context *)malloc(sizeof(mbedtls_ssl_context)); - if (o->ssl == NULL){ - goto cleanup; - } - o->conf = (mbedtls_ssl_config *)malloc(sizeof(mbedtls_ssl_config)); - if (o->conf == NULL){ - goto cleanup; - } - o->cacert = (mbedtls_x509_crt *)malloc(sizeof(mbedtls_x509_crt)); - if (o->cacert == NULL){ - goto cleanup; - } - o->cert = (mbedtls_x509_crt *)malloc(sizeof(mbedtls_x509_crt)); - if (o->cert == NULL){ - goto cleanup; - } - o->pkey = (mbedtls_pk_context *)malloc(sizeof(mbedtls_pk_context)); - if (o->pkey == NULL){ - goto cleanup; - } - - o->base.type = &ussl_socket_type; - o->sock = sock; - - mbedtls_platform_setup(NULL); - - 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) - mbedtls_debug_set_threshold(100); - #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->ca.u_obj != mp_const_none) { - size_t cert_len; - const byte *cert = (const byte *)mp_obj_str_get_data(args->ca.u_obj, &cert_len); - - ret = mbedtls_x509_crt_parse(o->cacert, cert, cert_len + 1); - if (ret != 0) { - ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA; // use general error for all cert errors - goto cleanup; - } - - uint32_t flags; - char xcbuf[256]; - memset( xcbuf, 0, 256); - - ret = mbedtls_x509_crt_verify( o->cacert, o->cacert, NULL, NULL, &flags, NULL, NULL ); - if( ret != 0 ) - { - QPY_MPUSSL_LOG("flags: %0x\n", flags); - ret = mbedtls_x509_crt_verify_info(xcbuf, sizeof(xcbuf), "\n", flags); - - if (flags == 0x200) - { - QPY_MPUSSL_LOG("mbedtls_x509_crt_verify IGNORE\n"); - } - else - { - mp_printf(&mp_plat_print, "[mbedtls](mbedtls_x509_crt_verify FAIL: %s) :\n", xcbuf); - ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; // use general error for all cert errors - goto cleanup; - } - } - else - { - QPY_MPUSSL_LOG("mbedtls_x509_crt_verify succeeded\n"); - } - - mbedtls_ssl_conf_ca_chain(o->conf, o->cacert, NULL); - mbedtls_ssl_conf_authmode(o->conf, MBEDTLS_SSL_VERIFY_REQUIRED); - mbedtls_ssl_conf_verify( o->conf, my_verify, 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; - } - } - } - - return MP_OBJ_FROM_PTR(o); - -cleanup: - if (o->pkey != NULL) - { - mbedtls_pk_free(o->pkey); free(o->pkey); o->pkey = NULL; - } - if (o->cert != NULL) - { - mbedtls_x509_crt_free(o->cert); free(o->cert); o->cert = NULL; - } - if (o->cacert != NULL) - { - mbedtls_x509_crt_free(o->cacert); free(o->cacert); o->cacert = NULL; - } - if (o->ssl != NULL) - { - mbedtls_ssl_free(o->ssl); free(o->ssl); o->ssl = NULL; - } - if (o->conf != NULL) - { - mbedtls_ssl_config_free(o->conf); free(o->conf); o->conf = NULL; - } - if (o->ctr_drbg != NULL) - { - mbedtls_ctr_drbg_free(o->ctr_drbg); free(o->ctr_drbg); o->ctr_drbg = NULL; - } - if (o->entropy != NULL) - { - mbedtls_entropy_free(o->entropy); free(o->entropy); o->entropy = NULL; - } - - 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 if (ret == MBEDTLS_ERR_X509_FILE_IO_ERROR) { - mp_raise_ValueError(MP_ERROR_TEXT("invalid ca")); - } 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); - - mp_printf(&mp_plat_print, "[mbedtls_ssl_read](socket_read 1:\n"); - 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); - - mp_printf(&mp_plat_print, "[mbedtls_ssl_write](socket_write 1:\n"); - - 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) { - if (self->pkey) - { - mbedtls_pk_free(self->pkey); - free(self->pkey); - self->pkey = NULL; - } - if (self->cert) - { - mbedtls_x509_crt_free(self->cert); - free(self->cert); - self->cert = NULL; - } - if (self->cacert) - { - mbedtls_x509_crt_free(self->cacert); - free(self->cacert); - self->cacert = NULL; - } - if (self->ssl) - { - mbedtls_ssl_free(self->ssl); - free(self->ssl); - self->ssl = NULL; - } - if (self->conf) - { - mbedtls_ssl_config_free(self->conf); - free(self->conf); - self->conf = NULL; - } - if (self->ctr_drbg) - { - mbedtls_ctr_drbg_free(self->ctr_drbg); - free(self->ctr_drbg); - self->ctr_drbg = NULL; - } - if (self->entropy) - { - mbedtls_entropy_free(self->entropy); - free(self->entropy); - self->entropy = NULL; - } - } - // 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, -}; - -MP_DEFINE_CONST_OBJ_TYPE( - ussl_socket_type, - MP_QSTR_ussl, - MP_TYPE_FLAG_NONE, - protocol, &ussl_socket_stream_p, - locals_dict, &ussl_socket_locals_dict - ); - -bool mp_obj_is_ussl_socket(mp_obj_t o) { - return mp_obj_is_type(o, &ussl_socket_type); -} - -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_ca, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, - { 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 diff --git a/ports/quectel/modutime.c b/ports/quectel/modutime.c deleted file mode 100644 index 1de09e4f5bea7..0000000000000 --- a/ports/quectel/modutime.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020-2021 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 "shared/timeutils/timeutils.h" -#include "utime_mphal.h" - -#if MICROPY_QPY_MODULE_UTIME - -#include "helios_debug.h" -#include "helios_rtc.h" - - -#define QPY_UTIME_LOG(msg, ...) custom_log(utime, msg, ##__VA_ARGS__) - -static mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) { - timeutils_struct_time_t tm; - int64_t seconds; - if (n_args == 0 || args[0] == mp_const_none) { - Helios_RTCTime rtc_tm = {0, 0, 0, 1, 1, 1970, 4}; - Helios_RTC_GetLocalTime(&rtc_tm); - seconds = timeutils_seconds_since_2000(rtc_tm.tm_year, rtc_tm.tm_mon, rtc_tm.tm_mday, rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec); - timeutils_seconds_since_2000_to_struct_time(seconds, &tm); - } - else - { - //modified by freddy @20211227 Fix the exception when c=utime.mktime(utime.localtime()) utime.localtime(c) is executed when no network is injected - seconds = mp_obj_get_int_truncated(args[0]) - 946656000; // Pawn - 2021-03-17 -Fixed bug:Return time error - // Pawn - 2020-12-10 -Fixed bug:Return time error - timeutils_seconds_since_2000_to_struct_time(seconds, &tm); - if (tm.tm_hour >= 24) - { - tm.tm_mday += 1; - tm.tm_hour = tm.tm_hour % 24; - - switch (tm.tm_mon) - { - case 1: - case 3: - case 5: - case 7: - case 8: - case 10: - case 12: - if (tm.tm_mday > 31) - { - tm.tm_mon += 1; - tm.tm_mday = tm.tm_mday % 31; - } - break; - case 4: - case 6: - case 9: - case 11: - if (tm.tm_mday > 30) - { - tm.tm_mon += 1; - tm.tm_mday = tm.tm_mday % 30; - } - break; - case 2: - if (((tm.tm_year%4 == 0) && (tm.tm_year%100 != 0)) || (tm.tm_year%400 == 0)) - { - if (tm.tm_mday > 29) - { - tm.tm_mon += 1; - tm.tm_mday = tm.tm_mday % 29; - } - } - else - { - if (tm.tm_mday > 28) - { - tm.tm_mon += 1; - tm.tm_mday = tm.tm_mday % 28; - } - } - break; - default: - QPY_UTIME_LOG("the value(%d) of month is invalid.\n", tm.tm_mon); - break; - } - - if (tm.tm_mon > 12) - { - tm.tm_year += 1; - tm.tm_mon = tm.tm_mon % 12; - } - } - } - 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); - Helios_RTCTime rtc_tm; - mp_uint_t time_unix; - // 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); - } - rtc_tm.tm_year = mp_obj_get_int(elem[0]); - rtc_tm.tm_mon = mp_obj_get_int(elem[1]); - rtc_tm.tm_mday = mp_obj_get_int(elem[2]); - rtc_tm.tm_hour = mp_obj_get_int(elem[3]); - rtc_tm.tm_min = mp_obj_get_int(elem[4]); - rtc_tm.tm_sec = mp_obj_get_int(elem[5]); - - if (0 >= (rtc_tm.tm_mon -= 2)) { /* 1..12 -> 11,12,1..10 */ - rtc_tm.tm_mon += 12; /* Puts Feb last since it has leap day */ - rtc_tm.tm_year -= 1; - } - time_unix = ((( - ( mp_uint_t ) (rtc_tm.tm_year/4 - rtc_tm.tm_year/100 + rtc_tm.tm_year/400 - + 367*rtc_tm.tm_mon/12 + rtc_tm.tm_mday) + rtc_tm.tm_year*365 - 719499)*24 - + rtc_tm.tm_hour)*60 + rtc_tm.tm_min)*60 + rtc_tm.tm_sec - 28800; - - return mp_obj_new_int_from_uint(time_unix); -} -static MP_DEFINE_CONST_FUN_OBJ_1(time_mktime_obj, time_mktime); - -/*return rtc seconds since power on*/ -static mp_obj_t time_time(void) -{ - long seconds=0; - seconds = Helios_RTC_GetSecond(); - return mp_obj_new_int(seconds); -} -MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time); - -#if 1 -static mp_obj_t time_set_timezone(mp_obj_t tz) -{ - int offset = mp_obj_get_int(tz); - if ((offset < -12) || (offset > 12)) - { - mp_raise_ValueError(MP_ERROR_TEXT("invalid value, timezone should be in [-12, +12].")); - } - Helios_RTC_SetTimeZoneOffset(offset); - return mp_obj_new_int(0); -} -static MP_DEFINE_CONST_FUN_OBJ_1(time_set_timezone_obj, time_set_timezone); -#endif - -static mp_obj_t time_get_timezone(void) -{ - int offset = Helios_RTC_GetTimeZoneOffset(); - return mp_obj_new_int(offset); -} -static MP_DEFINE_CONST_FUN_OBJ_0(time_get_timezone_obj, time_get_timezone); - - - -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_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_setTimeZone), MP_ROM_PTR(&time_set_timezone_obj) }, - { MP_ROM_QSTR(MP_QSTR_getTimeZone), MP_ROM_PTR(&time_get_timezone_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); - -#endif /* MICROPY_QPY_MODULE_UTIME */ diff --git a/ports/quectel/mpconfigport.h b/ports/quectel/mpconfigport.h index 6cf8f636ec24e..9401d02d1a6af 100644 --- a/ports/quectel/mpconfigport.h +++ b/ports/quectel/mpconfigport.h @@ -44,6 +44,7 @@ #define MICROPY_PY_IO (1) #define MICROPY_PY_JSON (1) #define MICROPY_VFS (1) +#define MICROPY_QPY_MODULE_UOS (1) #define MICROPY_PY_VFS (0) #define MICROPY_PY_TIME (0) #define MICROPY_PY_HEAPQ (0) @@ -94,7 +95,7 @@ #define MICROPY_PY_THREAD (1) #define MICROPY_PY_THREAD_GIL (1) -#define MICROPY_ENABLE_CALLBACK_DEAL (1) +#define MICROPY_ENABLE_CALLBACK_DEAL (0) #define MICROPY_READER_VFS (1) #define MICROPY_KBD_EXCEPTION (1) @@ -142,20 +143,8 @@ #define MICROPY_SSL_MBEDTLS (1) #endif -#if defined(PLAT_Qualcomm) -#define mp_type_fileio mp_type_vfs_efs_fileio -#define mp_type_textio mp_type_vfs_efs_textio -#elif defined(PLAT_EIGEN) -#define mp_type_fileio mp_type_vfs_lfs2_fileio -#define mp_type_textio mp_type_vfs_lfs2_textio -#elif defined(PLAT_EIGEN_718) -#define mp_type_fileio mp_type_vfs_lfs2_fileio -#define mp_type_textio mp_type_vfs_lfs2_textio -#else #define mp_type_fileio mp_type_vfs_lfs1_fileio #define mp_type_textio mp_type_vfs_lfs1_textio -#endif - // type definitions for the specific machine @@ -173,32 +162,7 @@ typedef long mp_off_t; #define MICROPY_GC_HEAP_SIZE (MICROPY_QPY_GC_HEAP_SIZE) #endif -#ifdef MICROPY_QPY_MAIN_TASK_STACK_SIZE -#define MP_QPY_TASK_STACK_SIZE (MICROPY_QPY_MAIN_TASK_STACK_SIZE) -#else -#if defined(PLAT_RDA) -#define MP_QPY_TASK_STACK_SIZE (32 * 1024) -#elif defined(PLAT_EIGEN) -#define MP_QPY_TASK_STACK_SIZE (32 * 1024) -#elif defined(PLAT_EIGEN_718) -#define MP_QPY_TASK_STACK_SIZE (8 * 1024) -#elif defined(PLAT_ECR6600) -#define MP_QPY_TASK_STACK_SIZE (8 * 1024) -#elif defined(PLAT_aic8800m40) -#define MP_QPY_TASK_STACK_SIZE (10 * 1024) -#elif defined(PLAT_Unisoc_8850) || defined(PLAT_Unisoc_8850_R02) - #if defined(BOARD_EC600GCN_LD) || defined(BOARD_EC800GCN_LD) || defined(BOARD_EC800GCN_LD_XBND) \ - || defined(BOARD_EC800GCN_LD_HRXM) || defined(BOARD_EC600GCN_LD_YM) || defined(BOARD_EC800GCN_TT) \ - || defined(BOARD_EG800GLA_LD) - #define MP_QPY_TASK_STACK_SIZE (16 * 1024) - #else - #define MP_QPY_TASK_STACK_SIZE (64 * 1024) - #endif -#else #define MP_QPY_TASK_STACK_SIZE (64 * 1024) -#endif -#endif - // We need to provide a declaration/definition of alloca() #include @@ -226,7 +190,7 @@ typedef long mp_off_t; #if MICROPY_PY_THREAD #define MICROPY_EVENT_POLL_HOOK \ do { \ - extern void mp_handle_pending(bool); \ + extern void mp_handle_pending(mp_handle_pending_behaviour_t behavior); \ mp_handle_pending(true); \ MP_THREAD_GIL_EXIT(); \ MP_THREAD_GIL_ENTER(); \ diff --git a/ports/quectel/mpconfigport.mk b/ports/quectel/mpconfigport.mk index 3eb1116478c94..a6aebebfcffc6 100644 --- a/ports/quectel/mpconfigport.mk +++ b/ports/quectel/mpconfigport.mk @@ -1,40 +1,10 @@ # Enable/disable modules and 3rd-party libs to be included in interpreter -ifeq ($(strip $(PLAT)), $(filter $(PLAT),EIGEN EIGEN_718)) - -MICROPY_VFS_LFS1=0 -MICROPY_VFS_LFS2=1 - -else ifeq ($(strip $(PLAT)), $(filter $(PLAT),Unisoc_8850 Unisoc_8850_R02)) - -MICROPY_VFS_LFS1=1 -MICROPY_VFS_LFS2=0 - -else ifeq ($(strip $(PLAT)), $(filter $(PLAT),Unisoc Unisoc_8910_R05 Unisoc_8910_R06)) - -MICROPY_VFS_LFS1=1 -MICROPY_VFS_LFS2=0 - -else ifeq ($(strip $(PLAT)), $(filter $(PLAT),SONY SONY_ALT1350)) - -MICROPY_VFS_LFS1=0 -MICROPY_VFS_LFS2=0 -MICROPY_VFS_QUECFS=1 - -else ifeq ($(strip $(PLAT)), $(filter $(PLAT),ASR_1602 ASR_1609)) - -MICROPY_VFS_LFS1=0 -MICROPY_VFS_LFS2=1 - -else ifeq ($(strip $(PLAT)), $(filter $(PLAT),ASR ASR_1803s ASR_1803sc)) +ifeq ($(strip $(PLAT)), $(filter $(PLAT),Unisoc Unisoc_8910_R05 Unisoc_8910_R06)) MICROPY_VFS_LFS1=1 MICROPY_VFS_LFS2=0 -else ifeq ($(strip $(PLAT)),ASR_1606) - -include $(TOP)/../../system/platform/ASR_1606/board/$(BOARD)/mpconfigboard.mk - ifeq ($(MICROPY_VFS_LFS_VERSION), 1) MICROPY_VFS_LFS1=1 MICROPY_VFS_LFS2=0 diff --git a/ports/quectel/mphalport.c b/ports/quectel/mphalport.c index e7f4591ce10c1..9c2f0d313d5f9 100644 --- a/ports/quectel/mphalport.c +++ b/ports/quectel/mphalport.c @@ -39,10 +39,8 @@ #include "mpconfigport.h" #include "helios_uart.h" #include "helios_rtc.h" -#if MICROPY_PY_KBD_EXCEPTION #include "shared/runtime/interrupt_char.h" #include "py/runtime.h" -#endif #define QPY_MTHREAD_SLEEP_DEAL_MSG_MAX_NUM (2 * MICROPY_SCHEDULER_DEPTH) static Helios_MsgQ_t qpy_mthread_sleep_queue = 0; @@ -152,39 +150,8 @@ void mp_main_thread_wakeup() static void mp_hal_stdin_cb(uint64_t ind_type, Helios_UARTNum port, uint64_t size) { if(MP_HAL_PORT_CHECK_OPEN) { -#if MICROPY_PY_KBD_EXCEPTION - if(IS_MAINPY_RUNNING_FLAG_TRUE() && Head_node == NULL) - { - uint64_t i = 0; - volatile unsigned char c = 0; - for(i= 0; i < size; i++) - { - if(Helios_UART_Read(QPY_REPL_UART, (void *)&c, sizeof(unsigned char)) >0 ) { - if (!IS_REPL_REFUSED() && (c == mp_interrupt_char)) { - // Signal keyboard interrupt to be raised as soon as the VM resumes - mp_sched_keyboard_interrupt(); - break; - } - continue; - } - break; - } - if(i < size) - { - for(; i < size; i++) - { - if(Helios_UART_Read(QPY_REPL_UART, (void *)&c, sizeof(unsigned char)) >0 ) { - continue; - } - break; - } - } - } - else -#endif { mp_main_thread_wakeup(); - } } } @@ -381,4 +348,3 @@ static bool mp_mthread_sleep_deal_is_inited(void) { return (0 != qpy_mthread_sleep_queue); } - diff --git a/ports/quectel/mphalport.h b/ports/quectel/mphalport.h index 21375137df4c3..4eab86c586d9e 100644 --- a/ports/quectel/mphalport.h +++ b/ports/quectel/mphalport.h @@ -30,32 +30,9 @@ #include "helios_os.h" #include "helios_uart.h" -#if defined(PLAT_RDA) -#define QPY_REPL_UART HELIOS_UART0 -#define HAL_TICK1S 16.384 -/*Due to low power consumption of BC25 series, the baud rate needs to be set to 57600, please do not modify.*/ -#define HELIOS_UART_BAUD HELIOS_UART_BAUD_57600 -#elif defined(PLAT_Qualcomm) -#define HAL_TICK1S 32.768 +#define HAL_TICK1S 32.768 #define QPY_REPL_UART HELIOS_UART3 #define HELIOS_UART_BAUD HELIOS_UART_BAUD_115200 -#elif defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) -#define HAL_TICK1S 3.25 -#define QPY_REPL_UART HELIOS_UART3 -#define HELIOS_UART_BAUD HELIOS_UART_BAUD_115200 -#elif defined(PLAT_ECR6600) -#define HAL_TICK1S 0.5 -#define QPY_REPL_UART HELIOS_UART2 -#define HELIOS_UART_BAUD HELIOS_UART_BAUD_115200 -#elif defined(PLAT_aic8800m40) -#define HAL_TICK1S 32.768 -#define QPY_REPL_UART HELIOS_UART1 -#define HELIOS_UART_BAUD HELIOS_UART_BAUD_115200 -#else -#define HAL_TICK1S 32.768 -#define QPY_REPL_UART HELIOS_UART3 -#define HELIOS_UART_BAUD HELIOS_UART_BAUD_115200 -#endif //mia.zhong @20220308 input接口多线程调用导致dump问题 typedef struct Input_ListNode diff --git a/ports/quectel/mpthreadport.c b/ports/quectel/mpthreadport.c index d8312b767303b..98073b6994b75 100644 --- a/ports/quectel/mpthreadport.c +++ b/ports/quectel/mpthreadport.c @@ -330,5 +330,4 @@ unsigned int mp_get_available_memory_size(void) return Helios_GetAvailableMemorySize(); } - -#endif // MICROPY_PY_THREAD \ No newline at end of file +#endif // MICROPY_PY_THREAD diff --git a/ports/quectel/mpthreadport.h b/ports/quectel/mpthreadport.h index 2f36bf9c1f06a..84e7347d3814b 100644 --- a/ports/quectel/mpthreadport.h +++ b/ports/quectel/mpthreadport.h @@ -68,4 +68,3 @@ void mp_thread_semphore_del(mp_thread_semphore_t *sem); void mp_new_thread_add(uint32_t th_id, uint32_t stack_size); #endif // MICROPY_INCLUDED_MPTHREADPORT_H - diff --git a/ports/quectel/quectel.mk b/ports/quectel/quectel.mk index a788f43a006f2..acd63236c1f02 100644 --- a/ports/quectel/quectel.mk +++ b/ports/quectel/quectel.mk @@ -1,35 +1,11 @@ -include plat.mk PLAT_DFLAGS = $(addprefix -D,$(DFLAGS)) PLAT_CFLAGS = $(QUEC_CFLAGS) PLAT_CFLAGS += -Wno-unused-parameter -Wformat=0 -Wno-unused-function -INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/config +INC += -I./boards/$(BOARD) INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/include -ifeq ($(strip $(PLAT)),Qualcomm) -INC += -I$(COMPILER_PATH)/armv7m-none-eabi/libc/include -INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api -INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/c-utility -INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/c-utility/inc -INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/c-utility/inc/azure_c_shared_utility -INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/c-utility/pal -INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/c-utility/pal/generic -INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/iothub_client -INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/iothub_client/inc -INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/iothub_client/inc/internal -INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/serializer -INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/serializer/inc -INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/umqtt -INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/umqtt/inc -INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/umqtt/inc/azure_umqtt_c -INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/qapi -INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/threadx_api -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include -INC += -I$(ROOT)/system/at -INC += -I$(ROOT)/system/esim -endif - INC += -I. INC += -I$(HEADER_BUILD) INC += -I$(TOP) @@ -40,6 +16,9 @@ INC += -I$(TOP)/lib/mp-readline INC += -I$(TOP)/lib/littlefs INC += -I$(TOP)/lib/netutils INC += -I$(TOP)/lib/timeutils +INC += -I$(TOP)/ports/quectel/core +INC += -I$(TOP)/ports/quectel/core/source +INC += -I$(TOP)/ports/quectel/core/py INC += -I$(ROOT)/peripheral INC += -I$(ROOT)/system/include INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/include @@ -53,20 +32,6 @@ INC += -I$(ROOT)/system/network INC += -I$(ROOT)/system/at INC += -I$(ROOT)/system/aliiot -ifeq ($(strip $(PLAT)),$(filter $(PLAT),ASR_1803s ASR_1803sc)) -INC += -I$(ROOT)/system/csd -INC += -I$(ROOT)/system/esim -endif -ifeq ($(strip $(PLAT)),ASR_1606) -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include -endif -ifeq ($(strip $(PLAT)),ASR_1602) -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include -endif -ifeq ($(strip $(PLAT)),ASR_1609) -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include -endif - ifeq ($(strip $(PLAT)),Unisoc) INC += -I$(ROOT)/system/lwip/$(strip $(PLAT)) INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include @@ -85,115 +50,13 @@ INC += -I$(ROOT)/system/at INC += -I$(ROOT)/system/esim endif -ifeq ($(strip $(PLAT)),$(filter $(PLAT),Unisoc_8910_R05 Unisoc_8910_R06)) -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT)) -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/apps -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/priv -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/prot -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/netif -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/netif/ppp -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/netif/ppp/polarssl -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix/arpa -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix/net -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix/netinet -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix/sys -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/stdc -INC += -I$(ROOT)/system/esim -endif - -ifeq ($(strip $(PLAT)),$(filter $(PLAT),EIGEN EIGEN_718)) -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT)) -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/lwip -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/lwip/apps -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/lwip/priv -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/lwip/prot -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/arch -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/netif -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/posix -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/posix/sys -endif - -ifeq ($(strip $(PLAT)),$(filter $(PLAT),SONY_ALT1350)) -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT)) -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/arch -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/lwip -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/lwip/priv -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/lwip/prot -endif - -ifeq ($(strip $(PLAT)),$(filter $(PLAT),Unisoc_8850 Unisoc_8850_R02)) -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT)) -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/apps -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/priv -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/prot -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/netif -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/netif/ppp -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/netif/ppp/polarssl -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix/arpa -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix/net -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix/netinet -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/posix/sys -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/compat/stdc -endif - -ifeq ($(strip $(PLAT)),RDA) -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT)) -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include/arch -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/apps -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/priv -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/prot -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/netif -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix/arpa -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix/net -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix/netinet -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix/sys -endif - -ifeq ($(strip $(PLAT)), $(filter $(PLAT),ASR ASR_1803s ASR_1803sc)) -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT)) -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include -INC += -I$(ROOT)/system/at -endif - -ifeq ($(strip $(PLAT)),ECR6600) -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT)) -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include -endif - -ifeq ($(strip $(PLAT)),aic8800m40) -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/lwip-STABLE-2_0_2_RELEASE_VER/ports/rtos/include -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/lwip-STABLE-2_0_2_RELEASE_VER/ports/rtos/include/arch -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/lwip-STABLE-2_0_2_RELEASE_VER/src/include -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/lwip-STABLE-2_0_2_RELEASE_VER/src/include/lwip -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/lwip-STABLE-2_0_2_RELEASE_VER/src/include/lwip/priv -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/lwip-STABLE-2_0_2_RELEASE_VER/src/include/lwip/prot -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/lwip-STABLE-2_0_2_RELEASE_VER/src/include/netif -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/lwip-STABLE-2_0_2_RELEASE_VER/src/include/posix -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/lwip-STABLE-2_0_2_RELEASE_VER/src/include/posix/sys -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/net_al -endif - -#ifeq ($(CONFIG_MBEDTLS), 1) +ifeq ($(CONFIG_MBEDTLS), 1) INC += -I$(ROOT)/system/mbedtls INC += -I$(ROOT)/system/mbedtls/include INC += -I$(ROOT)/system/mbedtls/include/mbedtls INC += -I$(ROOT)/system/mbedtls/library INC += -I$(ROOT)/system/mbedtls/port/helios/inc -#endif +endif INC += -I$(ROOT)/system/network INC += -I$(ROOT)/system/os @@ -201,182 +64,6 @@ INC += -I$(ROOT)/system/startup INC += -I$(ROOT)/system/fota INC += -I$(ROOT)/system/bt INC += -I$(ROOT)/system/at -ifeq (y, $(CONFIG_LVGL)) -INC += -I$(TOP)/lib/lvgl -INC += -I$(TOP)/lib/lvgl/src -INC += -I$(TOP)/lib/lvgl/src/core -INC += -I$(TOP)/lib/lvgl/src/draw -INC += -I$(TOP)/lib/lvgl/src/extra -INC += -I$(TOP)/lib/lvgl/src/font -INC += -I$(TOP)/lib/lvgl/src/gpu -INC += -I$(TOP)/lib/lvgl/src/hal -INC += -I$(TOP)/lib/lvgl/src/misc -INC += -I$(TOP)/lib/lvgl/src/widgts -endif -INC += -I$(ROOT)/driver -INC += -I$(ROOT)/driver/lcd -ifeq (y, $(CONFIG_QRCODE)) -INC += -I$(ROOT)/components/qrcode -endif -ifeq ($(CONFIG_JRTC), y) -INC += -I$(ROOT)/components/jrtc/inc -endif - -ifeq ($(CONFIG_SENSOR_VC9202), y) -INC += -I$(ROOT)/components/sensor/VC9202/inc -INC += -I$(ROOT)/components/sensor/VC9202/algo/inc -endif - -ifeq (y, $(CONFIG_QUECTHING)) -INC += -I$(ROOT)/components/quecsdk/cloud -INC += -I$(ROOT)/components/quecsdk/driverLayer -INC += -I$(ROOT)/components/quecsdk/thirdLib/mqtt -INC += -I$(ROOT)/components/quecsdk/thirdLib/cJSON -INC += -I$(ROOT)/components/quecsdk/kernel -endif -ifeq ($(CONFIG_SPINAND), y) -INC += -I$(ROOT)/components/fs/include -INC += -I$(ROOT)/components/fs/yaffs/src/direct -INC += -I$(ROOT)/components/fs/yaffs/src/port -INC += -I$(ROOT)/components/fs/yaffs/src -INC += -I$(ROOT)/components/fs/yaffs -endif -ifeq ($(CONFIG_RTMP), y) -INC += -I$(ROOT)/components/rtmpdump/librtmp/inc -INC += -I$(ROOT)/components/rtmpdump/libz/inc -endif -INC += -I$(ROOT)/utilities -ifeq ($(CONFIG_JPEG), y) -INC += -I$(ROOT)/components/libjpeg-turbo/include -INC += -I$(ROOT)/components/libjpeg-turbo -INC += -I$(ROOT)/components/libjpeg-turbo/src -INC += -I$(ROOT)/components/libjpeg-turbo/src/simd -endif -ifeq ($(CONFIG_POC_BND), y) -INC += -I$(ROOT)/components/poc -INC += -I$(ROOT)/components/poc/bnd/inc -endif -ifeq ($(CONFIG_POC_BND_XIN), y) -INC += -I$(ROOT)/components/poc -INC += -I$(ROOT)/components/poc/bnd_xin/inc -endif -ifeq ($(CONFIG_POC_SL), y) -INC += -I$(ROOT)/components/poc -INC += -I$(ROOT)/components/poc/sl/inc -endif -ifeq ($(CONFIG_POC_QS), y) -INC += -I$(ROOT)/components/poc -INC += -I$(ROOT)/components/poc/qs/inc -endif -#Carlos.Meng add 2024/02/22 -ifeq ($(CONFIG_POC_QS_R07), y) -INC += -I$(ROOT)/components/poc -INC += -I$(ROOT)/components/poc/qs/inc -endif -#Stephen.Gao add 2022/11/23 -ifeq ($(CONFIG_POC_ZZD), y) -INC += -I$(ROOT)/components/poc -INC += -I$(ROOT)/components/poc/zzd/inc -endif -#Stephen.Gao add 2023/01/06 -ifeq ($(CONFIG_POC_YDWL), y) -INC += -I$(ROOT)/components/poc -INC += -I$(ROOT)/components/poc/ydwl/inc -endif - -ifeq ($(CONFIG_POC_SLPOC), y) -INC += -I$(ROOT)/components/poc -I$(ROOT)/components/poc/slpoc/src -INC += -I$(ROOT)/components/poc/slpoc/inc -SRC_QSTR += $(ROOT)/components/poc/slpoc/src/modpoc_slpoc.c -endif - -ifeq ($(CONFIG_POC_RDA_BND), y) -INC += -I$(ROOT)/components/poc -I$(ROOT)/components/poc/rda_bnd/src -INC += -I$(ROOT)/components/poc/rda_bnd/inc -SRC_QSTR += $(ROOT)/components/poc/rda_bnd/src/modpocrda.c -endif - -ifeq ($(CONFIG_POC_RDA_BND_XIN), y) -INC += -I$(ROOT)/components/poc -I$(ROOT)/components/poc/rda_bnd_xin/src -INC += -I$(ROOT)/components/poc/rda_bnd_xin/inc -SRC_QSTR += $(ROOT)/components/poc/rda_bnd_xin/src/modpocrda.c -endif - -ifeq ($(CONFIG_POC_TID), y) -INC += -I$(ROOT)/components/poc -I$(ROOT)/components/poc/tid/src -INC += -I$(ROOT)/components/poc/tid/inc -SRC_QSTR += $(ROOT)/components/poc/tid/src/modpoc_tid.c -endif - -ifeq (y,$(CONFIG_DECODE_ZBAR)) -INC += -I$(ROOT)/components/decode/ZBar/zbar -INC += -I$(ROOT)/components/decode/ZBar/include -INC += -I$(ROOT)/components/decode/ZBar/zbar/decoder -INC += -I$(ROOT)/components/decode/ZBar/zbar/qrcode -endif -ifeq (y,$(CONFIG_DECODE_QUECTEL)) -INC += -I$(ROOT)/components/decode/quectel/inc -endif - -ifeq (y,$(CONFIG_DECODE_QINGYA)) -ifneq ($(strip $(PLAT)),ASR) -ifneq ($(strip $(PLAT)),ASR_1606) -INC += -I$(ROOT)/components/decode/qingya -endif -endif -endif - -ifeq ($(CONFIG_SPI_SDCARD), y) -INC += -I$(ROOT)/components/fs/fatfs/include -endif - -ifeq ($(CONFIG_AUDIO_G711_COMPRESS), y) -INC += -I$(ROOT)/components/audio/G711 -endif -ifeq ($(strip $(PLAT)),EIGEN) -INC += -I$(ROOT)/components/audio -endif - -ifeq ($(CONFIG_GMSSL), y) -INC += -I$(ROOT)/components/GMSSL/include -INC += -I$(ROOT)/components/GMSSL/include/gmssl -endif - -ifeq ($(CONFIG_GB2312), y) -INC += -I$(ROOT)/components/decode/gb2312 -endif - -ifeq ($(CONFIG_ESIMSDK), y) -INC += -I$(ROOT)/components/esim/inc -endif - -ifeq ($(CONFIG_ESIM_IPA), y) -INC += -I$(ROOT)/system/esim -endif - -ifeq ($(CONFIG_AUDIO_G729_COMPRESS), y) -INC += -I$(ROOT)/components/audio/G729 -INC += -I$(ROOT)/components/audio/G729/src -INC += -I$(ROOT)/components/audio/G729/include -endif - -ifeq ($(CONFIG_NFC_SL6320), y) -INC += -I$(ROOT)/components/NFC/SL6320 -endif - -ifeq ($(CONFIG_VOIP), y) -INC += -I$(ROOT)/components/voip/libexosip2/include -INC += -I$(ROOT)/components/voip/libosip2/include -INC += -I$(ROOT)/components/voip/rtp -endif - -ifeq ($(CONFIG_ETHERNET_W5500), y) -INC += -I$(ROOT)/components/ethernet/wiznet -endif - -ifeq ($(CONFIG_SLIP), y) -INC += -I$(ROOT)/components/slip -endif ifeq ($(MICROPY_VFS_QUECFS),1) QUEC_MOD_CFLAGS += -DMICROPY_VFS_QUECFS=1 @@ -392,31 +79,8 @@ QUEC_SRC += \ QUEC_SRC_MOD += \ gccollect.c \ moduos.c \ - modutime.c \ - modsocket.c \ - modostimer.c \ - modfota.c \ - callbackdeal.c \ - modmachine.c \ - machine_pin.c \ - machine_wdt.c \ - machine_rtc.c \ - machine_uart.c \ - machine_timer.c \ - moddev.c \ - misc_power.c \ - modmisc.c \ - misc_usbnet.c \ - modsim.c \ - modnet.c \ - moddatacall.c \ - machine_extint.c \ - misc_adc.c \ - misc_pwm.c \ - modexample.c \ - machine_iic.c \ - machine_hw_spi.c \ - utime_mphal.c \ modflashdev.c \ - modussl_mbedtls.c \ modhelios.c + +# py modules define +QUEC_PY_MOD = modules/modules.py diff --git a/ports/quectel/utime_mphal.c b/ports/quectel/utime_mphal.c deleted file mode 100644 index a208971ee50e5..0000000000000 --- a/ports/quectel/utime_mphal.c +++ /dev/null @@ -1,110 +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 - * Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. - * - * 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 "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_TIME_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_TIME_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_TIME_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_get_int_truncated(start_in); - mp_uint_t end = mp_obj_get_int_truncated(end_in); - //mp_obj_get_int_truncated - // 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_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_TIME_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/ports/quectel/utime_mphal.h b/ports/quectel/utime_mphal.h deleted file mode 100644 index 5bb1d493b1fcd..0000000000000 --- a/ports/quectel/utime_mphal.h +++ /dev/null @@ -1,43 +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 - * Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. - * - * 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 From ff1284594ebfe87ee7ff8be62b34976f2162d936 Mon Sep 17 00:00:00 2001 From: Nikola Neskovic Date: Thu, 5 Mar 2026 16:45:11 +0100 Subject: [PATCH 03/13] quectel: Code formatting fix. --- ports/quectel/gccollect.c | 52 +++---- ports/quectel/gccollect.h | 11 +- ports/quectel/main.c | 176 +++++++++++---------- ports/quectel/modflashdev.c | 34 ++--- ports/quectel/modhelios.c | 4 +- ports/quectel/moduos.c | 102 ++++++------- ports/quectel/mpconfigport.h | 127 ++++++++++------ ports/quectel/mphalport.c | 285 ++++++++++++++++------------------- ports/quectel/mphalport.h | 6 +- ports/quectel/mpthreadport.c | 37 +++-- 10 files changed, 425 insertions(+), 409 deletions(-) diff --git a/ports/quectel/gccollect.c b/ports/quectel/gccollect.c index e72f2678737d8..344f507074f1a 100644 --- a/ports/quectel/gccollect.c +++ b/ports/quectel/gccollect.c @@ -33,37 +33,34 @@ #include "gccollect.h" #if defined(PLAT_RDA) -unsigned int ReadSP(void) -{ +unsigned int ReadSP(void) { uint32_t res; __asm volatile ( "move %0, $29\n" - :"=r"(res) + : "=r" (res) : : - ); - + ); + return res; } #elif defined(PLAT_ECR6600) #else -unsigned int ReadSP(void) -{ +unsigned int ReadSP(void) { uint32_t res; __asm volatile ( "mov %0, r13\n" - :"=r"(res) + : "=r" (res) : : - ); - + ); + return res; } #endif -void gc_stacktop_set(void * ptr) -{ +void gc_stacktop_set(void *ptr) { MP_STATE_PORT(global_stacktop_ptr) = ptr; } @@ -72,31 +69,26 @@ void gc_collect(void) { #if 0 uint32_t start = mp_hal_ticks_us(); #endif -#if defined(PLAT_ECR6600) - int val = 0; -#endif + #if defined(PLAT_ECR6600) + int val = 0; + #endif // start the GC gc_collect_start(); -#if defined(PLAT_ECR6600) - uintptr_t sp = (uintptr_t)&val; -#else + #if defined(PLAT_ECR6600) + uintptr_t sp = (uintptr_t)&val; + #else // get the registers and the sp uintptr_t sp = (uintptr_t)ReadSP(); -#endif - if(mp_is_python_thread()) - { + #endif + if (mp_is_python_thread()) { // trace the stack, including the registers (since they live on the stack in this function) gc_collect_root((void **)sp, ((uint32_t)MP_STATE_THREAD(stack_top) - sp) / sizeof(uint32_t)); - } - else if(NULL != MP_STATE_PORT(global_stacktop_ptr)) - { + } else if (NULL != MP_STATE_PORT(global_stacktop_ptr)) { gc_collect_root((void **)sp, ((uint32_t)MP_STATE_PORT(global_stacktop_ptr) - sp) / sizeof(uint32_t)); + } else { + // do nothing } - else - { - //do nothing - } - + // trace root pointers from any threads #if MICROPY_PY_THREAD mp_thread_gc_others(); @@ -117,4 +109,4 @@ void gc_collect(void) { #endif } -MP_REGISTER_ROOT_POINTER(volatile void * global_stacktop_ptr); +MP_REGISTER_ROOT_POINTER(volatile void *global_stacktop_ptr); diff --git a/ports/quectel/gccollect.h b/ports/quectel/gccollect.h index 9ce6896e47df7..6b3521ef46c1e 100644 --- a/ports/quectel/gccollect.h +++ b/ports/quectel/gccollect.h @@ -27,15 +27,14 @@ #ifndef __MICROPY_INCLUDED_QUECTEL_GCCOLLECT_H__ #define __MICROPY_INCLUDED_QUECTEL_GCCOLLECT_H__ -void gc_stacktop_set(void * ptr); +void gc_stacktop_set(void *ptr); void gc_collect(void); -//Set a stack address as the end address of the GC collection -//Do not add {} to the macro definition to prevent the scoping of stack_dummy from changing -#define GC_STACKTOP_SET() int stack_dummy;gc_stacktop_set(&stack_dummy); +// Set a stack address as the end address of the GC collection +// Do not add {} to the macro definition to prevent the scoping of stack_dummy from changing +#define GC_STACKTOP_SET() int stack_dummy; gc_stacktop_set(&stack_dummy); -//Clears the gc collection end stack pointer for global non-Python threads +// Clears the gc collection end stack pointer for global non-Python threads #define GC_STACKTOP_CLEAR() gc_stacktop_set(NULL); #endif - diff --git a/ports/quectel/main.c b/ports/quectel/main.c index 23fbe9275e25c..8d85193288116 100644 --- a/ports/quectel/main.c +++ b/ports/quectel/main.c @@ -59,48 +59,52 @@ Helios_Thread_t ql_micropython_task_ref; #define MP_TASK_STACK_SIZE (MP_QPY_TASK_STACK_SIZE) -#define MP_TASK_STACK_LEN (MP_TASK_STACK_SIZE/sizeof(uint32_t)) +#define MP_TASK_STACK_LEN (MP_TASK_STACK_SIZE / sizeof(uint32_t)) #if (defined(PLAT_ASR) || defined(PLAT_Unisoc) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_Qualcomm) \ - || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_Unisoc_8910_R06) || defined(PLAT_ASR_1602)) //support + || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_Unisoc_8910_R06) || defined(PLAT_ASR_1602)) // support #define QPY_ASSERT_SUPPORT 1 #endif void nlr_jump_fail(void *val) { -#if QPY_ASSERT_SUPPORT + #if QPY_ASSERT_SUPPORT Helios_Assert(__func__, __FILE__, __LINE__, ""); -#endif - while(1); + #endif + while (1) { + ; + } } void NORETURN __fatal_error(const char *msg) { -#if QPY_ASSERT_SUPPORT + #if QPY_ASSERT_SUPPORT Helios_Assert(msg, __FILE__, __LINE__, ""); -#endif - while(1); + #endif + while (1) { + ; + } } #ifndef NDEBUG #if !defined(PLAT_Qualcomm) void MP_WEAK __assert_func(const char *file, int line, const char *func, const char *expr) { -#if QPY_ASSERT_SUPPORT + #if QPY_ASSERT_SUPPORT Helios_Assert(expr, file, line, ""); -#else + #else printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line); -#endif + #endif __fatal_error("Assertion failed"); } #else void __assert_fail(const char *__message, - const char *__file, int __line, - const char *__function) { -#if QPY_ASSERT_SUPPORT - Helios_Assert(__message, __file, __line, ""); -#else - printf("Assertion '%s' failed, at file %s:%d\n", __message, __file, __line); -#endif - __fatal_error("Assertion failed"); + const char *__file, int __line, + const char *__function) { + #if QPY_ASSERT_SUPPORT + Helios_Assert(__message, __file, __line, ""); + #else + printf("Assertion '%s' failed, at file %s:%d\n", __message, __file, __line); + #endif + __fatal_error("Assertion failed"); } #endif @@ -108,15 +112,21 @@ void __assert_fail(const char *__message, static char *stack_top; #if MICROPY_ENABLE_GC +#if defined(PLAT_ECR6600) +static char __attribute__((__section__(".data"))) heap[MICROPY_GC_HEAP_SIZE]; +#elif defined(PLAT_SONY_ALT1350) +static char __attribute__((__section__("gpm1_working_data"))) heap[MICROPY_GC_HEAP_SIZE]; +#else static char heap[MICROPY_GC_HEAP_SIZE]; #endif +#endif extern pyexec_mode_kind_t pyexec_mode_kind; #if MICROPY_PY_KBD_EXCEPTION MAINPY_RUNNING_FLAG_DEF MAINPY_INTERRUPT_BY_KBD_FLAG_DEF -SET_MAINPY_RUNNING_TIMER_DEF + SET_MAINPY_RUNNING_TIMER_DEF #endif #if MICROPY_PY_SOFT_RESET @@ -126,90 +136,101 @@ static int vm_softreset_flag = 0; #define SOFTRESET_FLAG_TRUE() (1 == vm_softreset_flag) #define SOFTRESET_FLAG_FALSE() (0 == vm_softreset_flag) #endif -void quecpython_task(void *arg) -{ - int stack_dummy; +void quecpython_task(void *arg) { + int stack_dummy; Helios_Thread_t id = 0; - void *stack_ptr = NULL; + void *stack_ptr = NULL; #if MICROPY_QPY_MODULE_POC && CONFIG_POC_BND_XIN - helios_debug( "start qpy_poc_register_task"); + helios_debug("start qpy_poc_register_task"); extern void qpy_poc_register_task(); qpy_poc_register_task(); #endif mp_mthread_sleep_deal_init(); -#if CONFIG_MBEDTLS + #if CONFIG_MBEDTLS mbedtls_platform_setup(NULL); -#endif + #endif - #if MICROPY_PY_THREAD + #if MICROPY_PY_THREAD id = Helios_Thread_GetID(); ql_micropython_task_ref = id; stack_ptr = Helios_Thread_GetStaskPtr(id); -#if defined(PLAT_ECR6600) || defined(PLAT_aic8800m40) + #if defined(PLAT_ECR6600) || defined(PLAT_aic8800m40) mp_thread_init(stack_ptr, MP_TASK_STACK_SIZE); // unit: Word -#else + #else mp_thread_init(stack_ptr, MP_TASK_STACK_LEN); -#endif - #endif + #endif + #endif - if(mp_hal_stdio_init()) return; + if (mp_hal_stdio_init()) { + return; + } soft_reset: - mp_stack_set_top((void *)&stack_dummy); -#if defined(PLAT_ECR6600) || defined(PLAT_aic8800m40) // unit: Byte + mp_stack_set_top((void *)&stack_dummy); + #if defined(PLAT_ECR6600) || defined(PLAT_aic8800m40) // unit: Byte mp_stack_set_limit(MP_TASK_STACK_SIZE * sizeof(uint32_t) - 1024); -#else + #else mp_stack_set_limit(MP_TASK_STACK_SIZE - 1024); -#endif - stack_top = (char*)&stack_dummy; + #endif + stack_top = (char *)&stack_dummy; #if MICROPY_ENABLE_GC gc_init(heap, heap + sizeof(heap)); #endif mp_init(); #if MICROPY_ENABLE_CALLBACK_DEAL - qpy_callback_deal_init(); + qpy_callback_deal_init(); #endif readline_init0(); - - // run boot-up scripts + + // run boot-up scripts + #if defined(PLAT_RDA) + pyexec_frozen_module("_boot_RDA.py"); + #elif defined(PLAT_Qualcomm) + pyexec_frozen_module("_boot_Qualcomm.py"); + #elif defined(BOARD_EC800ECN_LC_WDF) + pyexec_frozen_module("_boot_WDF.py");// EIGEN WDF CUNSTOMER BOOT WITH SINGLE FILE SYSTEM + #elif defined(PLAT_ECR6600) || defined(PLAT_aic8800m40) + pyexec_frozen_module("_boot_WIFI.py"); + #elif defined(BOARD_EC600GCN_LA_CDD) + pyexec_frozen_module("_boot_dsds.py"); + #elif defined(PLAT_SONY_ALT1350) + pyexec_frozen_module("_boot_SONY.py", false); + #else pyexec_frozen_module("_boot.py", false); + #endif if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL - #if MICROPY_PY_KBD_EXCEPTION - && MAINPY_INTERRUPT_BY_KBD_FLAG_FALSE() - #endif - ) - { + #if MICROPY_PY_KBD_EXCEPTION + && MAINPY_INTERRUPT_BY_KBD_FLAG_FALSE() + #endif + ) { #if MICROPY_PY_SOFT_RESET SOFTRESET_FLAG_CLEAR(); #endif - + #if MICROPY_PY_KBD_EXCEPTION MAINPY_RUNNING_FLAG_SET(); #endif - + int ret = pyexec_file_if_exists("/usr/main.py"); if (ret & PYEXEC_FORCED_EXIT) { goto soft_reset_exit; } - + #if MICROPY_PY_KBD_EXCEPTION MAINPY_RUNNING_FLAG_CLEAR(); - if(RET_KBD_INTERRUPT == ret) - { + if (RET_KBD_INTERRUPT == ret) { MAINPY_INTERRUPT_BY_KBD_FLAG_SET(); } #endif - + #if MICROPY_PY_SOFT_RESET - if((PYEXEC_SOFTRESET & ret) == PYEXEC_SOFTRESET) { + if ((PYEXEC_SOFTRESET & ret) == PYEXEC_SOFTRESET) { SOFTRESET_FLAG_SET(); } #endif - } - else - { + } else { #if MICROPY_PY_KBD_EXCEPTION MAINPY_INTERRUPT_BY_KBD_FLAG_CLEAR(); #endif @@ -218,56 +239,55 @@ void quecpython_task(void *arg) #endif } - if(1 + if (1 #if MICROPY_PY_KBD_EXCEPTION && MAINPY_INTERRUPT_BY_KBD_FLAG_FALSE() #endif #if MICROPY_PY_SOFT_RESET && SOFTRESET_FLAG_FALSE() #endif - ) - { + ) { #if MICROPY_PY_SOFT_RESET nlr_buf_t nlr; nlr.ret_val = NULL; if (nlr_push(&nlr) == 0) { #endif - for (;;) { - if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { - if (pyexec_raw_repl() != 0) { - break; - } - } else { - if (pyexec_friendly_repl() != 0) { - break; - } + for (;;) { + if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { + if (pyexec_raw_repl() != 0) { + break; + } + } else { + if (pyexec_friendly_repl() != 0) { + break; } } - #if MICROPY_PY_SOFT_RESET - nlr_pop(); - } else { - mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); } + #if MICROPY_PY_SOFT_RESET + nlr_pop(); + } else { + mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); + } #endif } soft_reset_exit: - #if MICROPY_PY_THREAD + #if MICROPY_PY_THREAD mp_thread_deinit(); #endif - gc_sweep_all(); + gc_sweep_all(); mp_hal_stdout_tx_str("MPY: soft reboot\r\n"); #if MICROPY_ENABLE_CALLBACK_DEAL qpy_callback_deal_deinit(); qpy_callback_para_link_free_all(); #endif - mp_deinit(); -#if !defined(PLAT_RDA) + mp_deinit(); + #if !defined(PLAT_RDA) fflush(stdout); -#endif + #endif goto soft_reset; } @@ -288,4 +308,4 @@ MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open); #endif -application_init(quecpython_task, "quecpython_task", (MP_TASK_STACK_SIZE)/1024, 0); +application_init(quecpython_task, "quecpython_task", (MP_TASK_STACK_SIZE) / 1024, 0); diff --git a/ports/quectel/modflashdev.c b/ports/quectel/modflashdev.c index b2aa939ceb425..2047e600414ce 100644 --- a/ports/quectel/modflashdev.c +++ b/ports/quectel/modflashdev.c @@ -33,7 +33,7 @@ #include "helios_flash.h" #include "helios_debug.h" -#define MOD_FLASHDEV_LOG(msg, ...) custom_log('flashdev', msg, ##__VA_ARGS__) +#define MOD_FLASHDEV_LOG(msg, ...) custom_log('flashdev', msg,##__VA_ARGS__) const mp_obj_type_t helios_flash_device_type; @@ -52,46 +52,46 @@ typedef struct _helios_flash_device_obj_t { char partition_name[32]; } helios_flash_device_obj_t; -static mp_obj_t helios_flash_device_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 helios_flash_device_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, 2, false); helios_flash_device_obj_t *self = mp_obj_malloc(helios_flash_device_obj_t, type); mp_buffer_info_t bufinfo; memset(self->partition_name, 0x0, sizeof(self->partition_name)); mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ); - if( bufinfo.len >= sizeof(self->partition_name)) { + if (bufinfo.len >= sizeof(self->partition_name)) { mp_raise_ValueError(MP_ERROR_TEXT("partition name is invalid")); } memcpy(self->partition_name, bufinfo.buf, bufinfo.len); - + self->block_size = mp_obj_get_int(args[1]); if (self->block_size <= 0) { mp_raise_ValueError(MP_ERROR_TEXT("invalid block size")); } - HeliosFlashPartiCtx *FlashPartiCtx = Helios_Flash_GetPartiCtx((const char*)self->partition_name); - if(!FlashPartiCtx) mp_raise_OSError(19); + HeliosFlashPartiCtx *FlashPartiCtx = Helios_Flash_GetPartiCtx((const char *)self->partition_name); + if (!FlashPartiCtx) { + mp_raise_OSError(19); + } uint32_t FlashPartiAddr = FlashPartiCtx->addr; size_t FlashPartiSize = FlashPartiCtx->size; MOD_FLASHDEV_LOG("flash addr:%x", FlashPartiAddr); MOD_FLASHDEV_LOG("flash size:%x", FlashPartiSize); - self->info.LfsStartAddress = (FlashPartiAddr) / self->block_size * self->block_size; -#if MICROPY_VFS_LFS2 + self->info.LfsStartAddress = (FlashPartiAddr) / self->block_size * self->block_size; + #if MICROPY_VFS_LFS2 self->info.LfsEndAddress = ((FlashPartiAddr + FlashPartiSize) / self->block_size) * self->block_size; -#else - self->info.LfsEndAddress = ((FlashPartiAddr + FlashPartiSize - 1) / self->block_size) * self->block_size; -#endif + #else + self->info.LfsEndAddress = ((FlashPartiAddr + FlashPartiSize - 1) / self->block_size) * self->block_size; + #endif self->block_count = FlashPartiSize / self->block_size; return MP_OBJ_FROM_PTR(self); } -static mp_obj_t helios_flash_device_readblocks(size_t n_args, const mp_obj_t *args) -{ +static mp_obj_t helios_flash_device_readblocks(size_t n_args, const mp_obj_t *args) { helios_flash_device_obj_t *self = MP_OBJ_TO_PTR(args[0]); uint32_t FlashAddrss = 0; uint32_t block_num = mp_obj_get_int(args[1]); @@ -110,8 +110,7 @@ static mp_obj_t helios_flash_device_readblocks(size_t n_args, const mp_obj_t *ar } static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(helios_flash_device_readblocks_obj, 3, 4, helios_flash_device_readblocks); -static mp_obj_t helios_flash_device_writeblocks(size_t n_args, const mp_obj_t *args) -{ +static mp_obj_t helios_flash_device_writeblocks(size_t n_args, const mp_obj_t *args) { helios_flash_device_obj_t *self = MP_OBJ_TO_PTR(args[0]); uint32_t block_num = mp_obj_get_int(args[1]); uint32_t offset = block_num * self->block_size; @@ -134,8 +133,7 @@ static mp_obj_t helios_flash_device_writeblocks(size_t n_args, const mp_obj_t *a } static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(helios_flash_device_writeblocks_obj, 3, 4, helios_flash_device_writeblocks); -static mp_obj_t helios_flash_device_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t arg_in) -{ +static mp_obj_t helios_flash_device_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t arg_in) { helios_flash_device_obj_t *self = self_in; mp_int_t cmd = mp_obj_get_int(cmd_in); mp_int_t block_num = mp_obj_get_int(arg_in); diff --git a/ports/quectel/modhelios.c b/ports/quectel/modhelios.c index 47aa360a3a081..68cacceea5c06 100644 --- a/ports/quectel/modhelios.c +++ b/ports/quectel/modhelios.c @@ -34,7 +34,7 @@ #include "quectel_version.h" -static mp_obj_t helios_platform(void) { +static mp_obj_t helios_platform(void) { char platform[64] = {0}; snprintf(platform, sizeof(platform), "%s%d.%d.%d", "heliossdk-v", VERSION_MAJOR, VERSION_MINOR, VERSION_MICRO); return mp_obj_new_str(platform, strlen(platform)); @@ -54,4 +54,4 @@ const mp_obj_module_t helios_module = { .globals = (mp_obj_dict_t *)&helios_module_globals, }; -MP_REGISTER_MODULE(MP_QSTR_helios, helios_module); \ No newline at end of file +MP_REGISTER_MODULE(MP_QSTR_helios, helios_module); diff --git a/ports/quectel/moduos.c b/ports/quectel/moduos.c index d9641b9895ff4..bece7c6021da0 100644 --- a/ports/quectel/moduos.c +++ b/ports/quectel/moduos.c @@ -50,16 +50,16 @@ extern const mp_obj_type_t mp_fat_vfs_type; static const qstr os_uname_info_fields[] = { - MP_QSTR_sysname, MP_QSTR_nodename,MP_QSTR_release, + MP_QSTR_sysname, MP_QSTR_nodename, MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine, MP_QSTR_qpyver, }; -static MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, sysname); -static MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, nodename); -static MP_DEFINE_STR_OBJ(os_uname_info_release_obj, MICROPY_VERSION_STRING); -static MP_DEFINE_STR_OBJ(os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE); -static MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, machine); -static MP_DEFINE_STR_OBJ(os_uname_info_qpyver_obj, QUECPYTHON_VERSION_STRING); +static MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, sysname); +static MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, nodename); +static MP_DEFINE_STR_OBJ(os_uname_info_release_obj, MICROPY_VERSION_STRING); +static MP_DEFINE_STR_OBJ(os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE); +static MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, machine); +static MP_DEFINE_STR_OBJ(os_uname_info_qpyver_obj, QUECPYTHON_VERSION_STRING); static MP_DEFINE_ATTRTUPLE( os_uname_info_obj, @@ -74,51 +74,51 @@ static MP_DEFINE_ATTRTUPLE( ); static mp_obj_t os_uname2(void) { - Helios_Dev_GetProductName((void *)sysname, sizeof(sysname)); + Helios_Dev_GetProductName((void *)sysname, sizeof(sysname)); Helios_Dev_GetModel((void *)nodename, sizeof(nodename)); - snprintf(machine, sizeof(machine), "%s with QUECTEL", nodename); - - os_uname_info_sysname_obj.len = strlen(sysname); - os_uname_info_nodename_obj.len = strlen(nodename); - os_uname_info_machine_obj.len = strlen(machine); - os_uname_info_qpyver_obj.len = strlen(QUECPYTHON_VERSION_STRING); - return (mp_obj_t)&os_uname_info_obj; + snprintf(machine, sizeof(machine), "%s with QUECTEL", nodename); + + os_uname_info_sysname_obj.len = strlen(sysname); + os_uname_info_nodename_obj.len = strlen(nodename); + os_uname_info_machine_obj.len = strlen(machine); + os_uname_info_qpyver_obj.len = strlen(QUECPYTHON_VERSION_STRING); + return (mp_obj_t)&os_uname_info_obj; } static MP_DEFINE_CONST_FUN_OBJ_0(os_uname2_obj, os_uname2); static mp_obj_t os_uname(void) { - char sysname[40] = {0}; - char nodname[20] = {0}; - char release[20] = {0}; - char machine[30] = {0}; - char version[128] = {0}; - //char qpy_ver[20] = {0}; + char sysname[40] = {0}; + char nodname[20] = {0}; + char release[20] = {0}; + char machine[30] = {0}; + char version[128] = {0}; + // char qpy_ver[20] = {0}; char mob_usb_product[64] = {0}; char mob_model_id[64] = {0}; - //char _qpy_ver[20] = {0}; + // char _qpy_ver[20] = {0}; Helios_Dev_GetProductName((void *)mob_usb_product, sizeof(mob_usb_product)); Helios_Dev_GetModel((void *)mob_model_id, sizeof(mob_model_id)); - //Helios_Dev_GetQpyVersion((void *)_qpy_ver, sizeof(_qpy_ver)); - - snprintf(sysname, sizeof(sysname), "sysname=%s", mob_usb_product); - snprintf(nodname, sizeof(nodname), "nodename=%s", mob_model_id); - snprintf(release, sizeof(release), "release=%s", MICROPY_VERSION_STRING); - snprintf(version, sizeof(version), "version=%s on %s", MICROPY_GIT_TAG, MICROPY_BUILD_DATE); - snprintf(machine, sizeof(machine), "machine=%s with QUECTEL", mob_model_id); - //snprintf(qpy_ver, sizeof(qpy_ver), "qpyver=%s", _qpy_ver); - - mp_obj_t tuple[6] = { - mp_obj_new_str(sysname, strlen(sysname)), - mp_obj_new_str(nodname, strlen(nodname)), - mp_obj_new_str(release, strlen(release)), - mp_obj_new_str(version, strlen(version)), - mp_obj_new_str(machine, strlen(machine)), - mp_obj_new_str("qpyver="QUECPYTHON_VERSION_STRING, strlen("qpyver="QUECPYTHON_VERSION_STRING)), - }; - + // Helios_Dev_GetQpyVersion((void *)_qpy_ver, sizeof(_qpy_ver)); + + snprintf(sysname, sizeof(sysname), "sysname=%s", mob_usb_product); + snprintf(nodname, sizeof(nodname), "nodename=%s", mob_model_id); + snprintf(release, sizeof(release), "release=%s", MICROPY_VERSION_STRING); + snprintf(version, sizeof(version), "version=%s on %s", MICROPY_GIT_TAG, MICROPY_BUILD_DATE); + snprintf(machine, sizeof(machine), "machine=%s with QUECTEL", mob_model_id); + // snprintf(qpy_ver, sizeof(qpy_ver), "qpyver=%s", _qpy_ver); + + mp_obj_t tuple[6] = { + mp_obj_new_str(sysname, strlen(sysname)), + mp_obj_new_str(nodname, strlen(nodname)), + mp_obj_new_str(release, strlen(release)), + mp_obj_new_str(version, strlen(version)), + mp_obj_new_str(machine, strlen(machine)), + mp_obj_new_str("qpyver="QUECPYTHON_VERSION_STRING, strlen("qpyver="QUECPYTHON_VERSION_STRING)), + }; + return mp_obj_new_tuple(6, tuple); } @@ -167,8 +167,8 @@ static const mp_rom_map_elem_t os_module_globals_table[] = { #if OS_URANDOM_SEED_ON_IMPORT { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&os_urandom___init___obj) }, #endif - { MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&os_uname_obj) }, - { MP_ROM_QSTR(MP_QSTR_uname2), MP_ROM_PTR(&os_uname2_obj) }, + { MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&os_uname_obj) }, + { MP_ROM_QSTR(MP_QSTR_uname2), MP_ROM_PTR(&os_uname2_obj) }, #if MICROPY_PY_OS_DUPTERM { MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&mp_uos_dupterm_obj) }, { MP_ROM_QSTR(MP_QSTR_dupterm_notify), MP_ROM_PTR(&os_dupterm_notify_obj) }, @@ -196,22 +196,22 @@ static const mp_rom_map_elem_t os_module_globals_table[] = { #if MICROPY_VFS_LFS2 { MP_ROM_QSTR(MP_QSTR_VfsLfs2), MP_ROM_PTR(&mp_type_vfs_lfs2) }, #endif - #if defined(PLAT_Qualcomm) - { MP_ROM_QSTR(MP_QSTR_VfsEfs), MP_ROM_PTR(&mp_type_vfs_efs) }, - #endif + #if defined(PLAT_Qualcomm) + { MP_ROM_QSTR(MP_QSTR_VfsEfs), MP_ROM_PTR(&mp_type_vfs_efs) }, + #endif #if defined(PLAT_Unisoc_8910_R05) || defined(PLAT_Unisoc_8910_R06) - { MP_ROM_QSTR(MP_QSTR_VfsTemp), MP_ROM_PTR(&mp_type_vfs_temp) }, + { MP_ROM_QSTR(MP_QSTR_VfsTemp), MP_ROM_PTR(&mp_type_vfs_temp) }, #endif #if defined(PLAT_Unisoc_8910_R05) || defined(PLAT_Unisoc_8910_R06) || (defined(PLAT_Unisoc_8850_R02) && !defined(BOARD_EC800GCN_LD_XBND)) - { MP_ROM_QSTR(MP_QSTR_VfsSd), MP_ROM_PTR(&mp_type_vfs_temp) }, + { MP_ROM_QSTR(MP_QSTR_VfsSd), MP_ROM_PTR(&mp_type_vfs_temp) }, #endif -#if MICROPY_VFS_FAT_SDIO + #if MICROPY_VFS_FAT_SDIO { MP_ROM_QSTR(MP_QSTR_VfsEmmc), MP_ROM_PTR(&mp_type_vfs_sdio_emmc) }, { MP_ROM_QSTR(MP_QSTR_VfsSd), MP_ROM_PTR(&mp_type_vfs_sdio_sd) }, -#endif -#if MICROPY_VFS_QUECFS + #endif + #if MICROPY_VFS_QUECFS { MP_ROM_QSTR(MP_QSTR_VfsQuecfs), MP_ROM_PTR(&mp_type_vfs_quecfs) }, -#endif + #endif #endif }; diff --git a/ports/quectel/mpconfigport.h b/ports/quectel/mpconfigport.h index 9401d02d1a6af..7d11368ef1b95 100644 --- a/ports/quectel/mpconfigport.h +++ b/ports/quectel/mpconfigport.h @@ -31,8 +31,8 @@ /****************************** user define ************************************/ // python grammar #define MICROPY_PY_ATTRTUPLE (1) -#define MICROPY_PY_BUILTINS_BYTEARRAY (1) -#define MICROPY_CPYTHON_COMPAT (1) +#define MICROPY_PY_BUILTINS_BYTEARRAY (1) +#define MICROPY_CPYTHON_COMPAT (1) // builtin op #define MICROPY_PY_BUILTINS_STR_OP_MODULO (1) @@ -42,7 +42,7 @@ // modules #define MICROPY_PY_IO (1) -#define MICROPY_PY_JSON (1) +#define MICROPY_PY_JSON (1) #define MICROPY_VFS (1) #define MICROPY_QPY_MODULE_UOS (1) #define MICROPY_PY_VFS (0) @@ -55,8 +55,8 @@ #define MICROPY_PY_ASYNCIO (0) #define MICROPY_PY_BINASCII_CRC32 (0) -#define MICROPY_PY_UCTYPES (MICROPY_QPY_PY_UCTYPES) -#define MICROPY_PY_DEFLATE (0) +#define MICROPY_PY_UCTYPES (MICROPY_QPY_PY_UCTYPES) +#define MICROPY_PY_DEFLATE (0) #define MICROPY_OPT_COMPUTED_GOTO (1) @@ -69,15 +69,15 @@ // You can disable the built-in MicroPython compiler by setting the following // config option to 0. If you do this then you won't get a REPL prompt, but you // will still be able to execute pre-compiled scripts, compiled with mpy-cross. -#define MICROPY_ENABLE_COMPILER (1) +#define MICROPY_ENABLE_COMPILER (1) #define MICROPY_ENABLE_GC (1) -#define MICROPY_PY_GC (1) +#define MICROPY_PY_GC (1) #define MICROPY_HELPER_REPL (1) #define MICROPY_ENABLE_EXTERNAL_IMPORT (1) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) -#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE) //decimal numbers support -#define MICROPY_USE_INTERNAL_PRINTF (0) +#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE) // decimal numbers support +#define MICROPY_USE_INTERNAL_PRINTF (0) #define MPZ_DIG_SIZE (16) #define MICROPY_PY_SYS (1) @@ -86,35 +86,35 @@ #define MICROPY_ERROR_REPORTING MICROPY_ERROR_REPORTING_NORMAL #define MICROPY_USE_INTERNAL_ERRNO (1) -#define MICROPY_ENABLE_SCHEDULER (1) -#define MICROPY_SCHEDULER_STATIC_NODES (0) -#define MICROPY_SCHEDULER_DEPTH (64)//8 -#define MICROPY_REPL_AUTO_INDENT (1) -#define MICROPY_PY_UTIME_MP_HAL (1) +#define MICROPY_ENABLE_SCHEDULER (1) +#define MICROPY_SCHEDULER_STATIC_NODES (0) +#define MICROPY_SCHEDULER_DEPTH (64)// 8 +#define MICROPY_REPL_AUTO_INDENT (1) +#define MICROPY_PY_UTIME_MP_HAL (1) -#define MICROPY_PY_THREAD (1) -#define MICROPY_PY_THREAD_GIL (1) +#define MICROPY_PY_THREAD (1) +#define MICROPY_PY_THREAD_GIL (1) #define MICROPY_ENABLE_CALLBACK_DEAL (0) #define MICROPY_READER_VFS (1) #define MICROPY_KBD_EXCEPTION (1) #define MICROPY_PY_SOFT_RESET (0) -#define MICROPY_PY_IO_FILEIO (1) -#define MICROPY_PY_BUILTINS_SLICE (1) -#define MICROPY_PY_BUILTINS_PROPERTY (1) -#define MICROPY_PY_BUILTINS_BYTEARRAY (1) -#define MICROPY_PY_BUILTINS_SET (1) -#define MICROPY_PY_BUILTINS_MEMORYVIEW (1) -#define MICROPY_PY_SYS_STDFILES (1) -#define MICROPY_PY_SYS_STDIO_BUFFER (1) -#define MICROPY_PY_STRUCT (1) -#define MICROPY_ENABLE_FINALISER (1) +#define MICROPY_PY_IO_FILEIO (1) +#define MICROPY_PY_BUILTINS_SLICE (1) +#define MICROPY_PY_BUILTINS_PROPERTY (1) +#define MICROPY_PY_BUILTINS_BYTEARRAY (1) +#define MICROPY_PY_BUILTINS_SET (1) +#define MICROPY_PY_BUILTINS_MEMORYVIEW (1) +#define MICROPY_PY_SYS_STDFILES (1) +#define MICROPY_PY_SYS_STDIO_BUFFER (1) +#define MICROPY_PY_STRUCT (1) +#define MICROPY_ENABLE_FINALISER (1) #define MICROPY_PY_BUILTINS_ENUMERATE (1) #define MICROPY_PY_BUILTINS_MIN_MAX (1) #if defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) -#define MICROPY_PY_URANDOM (1) -#define MICROPY_PY_URANDOM_EXTRA_FUNCS (1) +#define MICROPY_PY_URANDOM (1) +#define MICROPY_PY_URANDOM_EXTRA_FUNCS (1) #endif #define MICROPY_PERSISTENT_CODE_LOAD (1) @@ -126,11 +126,11 @@ #endif #if defined(PLAT_Unisoc) \ - || defined(PLAT_Unisoc_8850) \ - || defined(PLAT_ASR_1803s) \ - || defined(PLAT_RDA) \ - || defined(PLAT_Qualcomm) \ - || defined(PLAT_ASR) + || defined(PLAT_Unisoc_8850) \ + || defined(PLAT_ASR_1803s) \ + || defined(PLAT_RDA) \ + || defined(PLAT_Qualcomm) \ + || defined(PLAT_ASR) #define MICROPY_PY_REPL_PASSWORD_PROTECT (1) #endif @@ -143,8 +143,20 @@ #define MICROPY_SSL_MBEDTLS (1) #endif +#if defined(PLAT_Qualcomm) +#define mp_type_fileio mp_type_vfs_efs_fileio +#define mp_type_textio mp_type_vfs_efs_textio +#elif defined(PLAT_EIGEN) +#define mp_type_fileio mp_type_vfs_lfs2_fileio +#define mp_type_textio mp_type_vfs_lfs2_textio +#elif defined(PLAT_EIGEN_718) +#define mp_type_fileio mp_type_vfs_lfs2_fileio +#define mp_type_textio mp_type_vfs_lfs2_textio +#else #define mp_type_fileio mp_type_vfs_lfs1_fileio #define mp_type_textio mp_type_vfs_lfs1_textio +#endif + // type definitions for the specific machine @@ -162,7 +174,32 @@ typedef long mp_off_t; #define MICROPY_GC_HEAP_SIZE (MICROPY_QPY_GC_HEAP_SIZE) #endif +#ifdef MICROPY_QPY_MAIN_TASK_STACK_SIZE +#define MP_QPY_TASK_STACK_SIZE (MICROPY_QPY_MAIN_TASK_STACK_SIZE) +#else +#if defined(PLAT_RDA) +#define MP_QPY_TASK_STACK_SIZE (32 * 1024) +#elif defined(PLAT_EIGEN) +#define MP_QPY_TASK_STACK_SIZE (32 * 1024) +#elif defined(PLAT_EIGEN_718) +#define MP_QPY_TASK_STACK_SIZE (8 * 1024) +#elif defined(PLAT_ECR6600) +#define MP_QPY_TASK_STACK_SIZE (8 * 1024) +#elif defined(PLAT_aic8800m40) +#define MP_QPY_TASK_STACK_SIZE (10 * 1024) +#elif defined(PLAT_Unisoc_8850) || defined(PLAT_Unisoc_8850_R02) + #if defined(BOARD_EC600GCN_LD) || defined(BOARD_EC800GCN_LD) || defined(BOARD_EC800GCN_LD_XBND) \ + || defined(BOARD_EC800GCN_LD_HRXM) || defined(BOARD_EC600GCN_LD_YM) || defined(BOARD_EC800GCN_TT) \ + || defined(BOARD_EG800GLA_LD) + #define MP_QPY_TASK_STACK_SIZE (16 * 1024) + #else + #define MP_QPY_TASK_STACK_SIZE (64 * 1024) + #endif +#else #define MP_QPY_TASK_STACK_SIZE (64 * 1024) +#endif +#endif + // We need to provide a declaration/definition of alloca() #include @@ -170,7 +207,7 @@ typedef long mp_off_t; #define STRINGIFY_VALUE(s) STRINGIFY(s) #define STRINGIFY(s) #s #define MICROPY_HW_BOARD_NAME STRINGIFY_VALUE(BOARD) -#define MICROPY_HW_MCU_NAME "QUECTEL" +#define MICROPY_HW_MCU_NAME "QUECTEL" // board specifics #define MICROPY_PY_SYS_PLATFORM STRINGIFY_VALUE(BOARD) #define QUECPYTHON_VERSION_STRING STRINGIFY_VALUE(QPYVER) @@ -189,17 +226,17 @@ typedef long mp_off_t; #if MICROPY_PY_THREAD #define MICROPY_EVENT_POLL_HOOK \ - do { \ - extern void mp_handle_pending(mp_handle_pending_behaviour_t behavior); \ - mp_handle_pending(true); \ - MP_THREAD_GIL_EXIT(); \ - MP_THREAD_GIL_ENTER(); \ - } while (0); + do { \ + extern void mp_handle_pending(mp_handle_pending_behaviour_t behavior); \ + mp_handle_pending(true); \ + MP_THREAD_GIL_EXIT(); \ + MP_THREAD_GIL_ENTER(); \ + } while (0); #else #define MICROPY_EVENT_POLL_HOOK \ - do { \ - extern void mp_handle_pending(bool); \ - mp_handle_pending(true); \ - asm ("waiti 0"); \ - } while (0); + do { \ + extern void mp_handle_pending(bool); \ + mp_handle_pending(true); \ + asm ("waiti 0"); \ + } while (0); #endif diff --git a/ports/quectel/mphalport.c b/ports/quectel/mphalport.c index 9c2f0d313d5f9..3e40740e69960 100644 --- a/ports/quectel/mphalport.c +++ b/ports/quectel/mphalport.c @@ -54,7 +54,7 @@ static int mthread_sleep_flag = 0; static uint8_t stdin_ringbuf_array[256]; ringbuf_t stdin_ringbuf = {stdin_ringbuf_array, sizeof(stdin_ringbuf_array), 0, 0}; -//mia.zhong @20220308 fix input of multi thread dump problem. +// mia.zhong @20220308 fix input of multi thread dump problem. Input_ListNode_t *Head_node = NULL; static uint8_t mp_hal_cdcPort_State = 1; @@ -63,101 +63,92 @@ static bool mp_mthread_sleep_deal_is_inited(void); static void mp_hal_stdin_cb(uint64_t ind_type, Helios_UARTNum port, uint64_t size); -void mp_hal_port_open(uint8_t state) -{ - mp_hal_cdcPort_State = state; - Helios_UARTConfig UARTConfig = { +void mp_hal_port_open(uint8_t state) { + mp_hal_cdcPort_State = state; + Helios_UARTConfig UARTConfig = { HELIOS_UART_BAUD, HELIOS_UART_DATABIT_8, HELIOS_UART_STOP_1, HELIOS_UART_PARITY_NONE, HELIOS_UART_FC_NONE }; - Helios_UARTInitStruct UARTInitStruct = {&UARTConfig, mp_hal_stdin_cb}; - - if(state == 1) { - Helios_UART_Deinit(QPY_REPL_UART); - if (Helios_UART_Init(QPY_REPL_UART, &UARTInitStruct)) { - mp_hal_cdcPort_State = 0; - } - } + Helios_UARTInitStruct UARTInitStruct = {&UARTConfig, mp_hal_stdin_cb}; + + if (state == 1) { + Helios_UART_Deinit(QPY_REPL_UART); + if (Helios_UART_Init(QPY_REPL_UART, &UARTInitStruct)) { + mp_hal_cdcPort_State = 0; + } + } } -//mia.zhong @20220308 fix input of multi thread dump problem. -static bool mp_mthread_sleep_deal_is_inited_child(Input_ListNode_t *node) -{ - return (0 != node->msg_q); +// mia.zhong @20220308 fix input of multi thread dump problem. +static bool mp_mthread_sleep_deal_is_inited_child(Input_ListNode_t *node) { + return 0 != node->msg_q; } -//mia.zhong @20220308 fix input of multi thread dump problem. -int mp_mthread_sleep_child(uint32_t ms) -{ +// mia.zhong @20220308 fix input of multi thread dump problem. +int mp_mthread_sleep_child(uint32_t ms) { mp_uint_t msg; int ret = -1; - if(Head_node) { - if(mp_mthread_sleep_deal_is_inited_child((Input_ListNode_t *)Head_node)) { + if (Head_node) { + if (mp_mthread_sleep_deal_is_inited_child((Input_ListNode_t *)Head_node)) { Head_node->mthread_sleep_flag = 1; - ret = Helios_MsgQ_Get(Head_node->msg_q, (mp_uint_t*)&msg, sizeof(msg), ms); + ret = Helios_MsgQ_Get(Head_node->msg_q, (mp_uint_t *)&msg, sizeof(msg), ms); Head_node->mthread_sleep_flag = 0; } } return ret; } -//mia.zhong @20220308 fix input of multi thread dump problem. -void mp_mthread_wakeup_child(void) -{ +// mia.zhong @20220308 fix input of multi thread dump problem. +void mp_mthread_wakeup_child(void) { mp_uint_t msg = 0; - if(Head_node) { - if(mp_mthread_sleep_deal_is_inited_child((Input_ListNode_t *)Head_node) && (Head_node->mthread_sleep_flag == 1)) { - Helios_MsgQ_Put(Head_node->msg_q, (const void*)(&msg), sizeof(mp_uint_t), 0); + if (Head_node) { + if (mp_mthread_sleep_deal_is_inited_child((Input_ListNode_t *)Head_node) && (Head_node->mthread_sleep_flag == 1)) { + Helios_MsgQ_Put(Head_node->msg_q, (const void *)(&msg), sizeof(mp_uint_t), 0); } } } -//main thread sleep -int mp_mthread_sleep(uint32_t ms) -{ +// main thread sleep +int mp_mthread_sleep(uint32_t ms) { mp_uint_t msg; int ret = -1; - if(mp_mthread_sleep_deal_is_inited()) { + if (mp_mthread_sleep_deal_is_inited()) { MTHREAD_SLEEP_ENTER(); - ret = Helios_MsgQ_Get(qpy_mthread_sleep_queue, (mp_uint_t*)&msg, sizeof(msg), ms); + ret = Helios_MsgQ_Get(qpy_mthread_sleep_queue, (mp_uint_t *)&msg, sizeof(msg), ms); MTHREAD_SLEEP_EXIT(); } return ret; } -//wake up main sleep -void mp_mthread_wakeup(void) -{ +// wake up main sleep +void mp_mthread_wakeup(void) { mp_uint_t msg = 0; - if(mp_mthread_sleep_deal_is_inited() && (IS_MTHREAD_IN_SLEEP())) { - Helios_MsgQ_Put(qpy_mthread_sleep_queue, (const void*)(&msg), sizeof(mp_uint_t), 0); + if (mp_mthread_sleep_deal_is_inited() && (IS_MTHREAD_IN_SLEEP())) { + Helios_MsgQ_Put(qpy_mthread_sleep_queue, (const void *)(&msg), sizeof(mp_uint_t), 0); } } -void mp_main_thread_wakeup() -{ - //mia.zhong @20220308 fix input of multi thread dump problem. +void mp_main_thread_wakeup() { + // mia.zhong @20220308 fix input of multi thread dump problem. if (Head_node != NULL) { mp_mthread_wakeup_child(); } else { - mp_mthread_wakeup();//forrest.liu@20210809 add for quecpython task repl using waiting msg + mp_mthread_wakeup();// forrest.liu@20210809 add for quecpython task repl using waiting msg } } -static void mp_hal_stdin_cb(uint64_t ind_type, Helios_UARTNum port, uint64_t size) -{ - if(MP_HAL_PORT_CHECK_OPEN) { +static void mp_hal_stdin_cb(uint64_t ind_type, Helios_UARTNum port, uint64_t size) { + if (MP_HAL_PORT_CHECK_OPEN) { { mp_main_thread_wakeup(); } - } + } } -int mp_hal_stdio_init(void) -{ +int mp_hal_stdio_init(void) { Helios_UARTConfig UARTConfig = { HELIOS_UART_BAUD_115200, HELIOS_UART_DATABIT_8, @@ -165,105 +156,96 @@ int mp_hal_stdio_init(void) HELIOS_UART_PARITY_NONE, HELIOS_UART_FC_NONE }; - + Helios_UARTInitStruct UARTInitStruct = {&UARTConfig, mp_hal_stdin_cb}; int ret = (int)Helios_UART_Init(QPY_REPL_UART, &UARTInitStruct); - if(ret) - { + if (ret) { return -1; } return 0; } -int mp_hal_stdin_rx_chr(void) -{ - while(1) - { - volatile unsigned char c = 0; - - if(MP_HAL_PORT_CHECK_OPEN && Helios_UART_Read(QPY_REPL_UART, (void *)&c, sizeof(unsigned char)) >0 ) { - return c; - } - - //forrest.liu@20210809 add for quecpython task repl using waiting msg +int mp_hal_stdin_rx_chr(void) { + while (1) { + volatile unsigned char c = 0; + + if (MP_HAL_PORT_CHECK_OPEN && Helios_UART_Read(QPY_REPL_UART, (void *)&c, sizeof(unsigned char)) > 0) { + return c; + } + + // forrest.liu@20210809 add for quecpython task repl using waiting msg MP_THREAD_GIL_EXIT(); - //mia.zhong @20220308 fix input of multi thread dump problem. - if (Head_node != NULL) + // mia.zhong @20220308 fix input of multi thread dump problem. + if (Head_node != NULL) { mp_mthread_sleep_child(HELIOS_WAIT_FOREVER); - else - mp_mthread_sleep(HELIOS_WAIT_FOREVER); + } else { + mp_mthread_sleep(HELIOS_WAIT_FOREVER); + } MP_THREAD_GIL_ENTER(); - + MICROPY_EVENT_POLL_HOOK } } -mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) -{ - if (!str|| !len) return 0; - if(MP_HAL_PORT_CHECK_OPEN) { - Helios_UART_Write(QPY_REPL_UART, (void *)str, len); +mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) { + if (!str || !len) { + return 0; + } + if (MP_HAL_PORT_CHECK_OPEN) { + Helios_UART_Write(QPY_REPL_UART, (void *)str, len); } return len; } -mp_uint_t mp_hal_ticks_ms(void) -{ - return (mp_uint_t)Helios_RTC_TicksToMs(); +mp_uint_t mp_hal_ticks_ms(void) { + return (mp_uint_t)Helios_RTC_TicksToMs(); } -mp_uint_t mp_hal_ticks_us(void) -{ - return (mp_uint_t)Helios_RTC_TicksToUs(); +mp_uint_t mp_hal_ticks_us(void) { + return (mp_uint_t)Helios_RTC_TicksToUs(); } -uint64_t mp_hal_time_ns(void) -{ +uint64_t mp_hal_time_ns(void) { return 0; } void mp_hal_delay_ms(mp_uint_t ms) { - mp_uint_t dt = 0; - mp_uint_t t0 = 0,t1 = 0; - Helios_Thread_t taskid = 0; - extern Helios_Thread_t ql_micropython_task_ref; - taskid = Helios_Thread_GetID(); - mp_uint_t qpy_mthread_sleep_deal_fun(mp_uint_t ms); - - if(ql_micropython_task_ref == taskid) - { - for(;;) - { - t0 = mp_hal_ticks_us(); - MP_THREAD_GIL_EXIT(); - mp_uint_t wait_time = qpy_mthread_sleep_deal_fun(ms); - MP_THREAD_GIL_ENTER(); - if(wait_time >= ms) - { - return; - } - MICROPY_EVENT_POLL_HOOK; - t1 = mp_hal_ticks_us(); - dt = t1 - t0; - if(dt / 1000 >= ms) - { - return; - } - ms -= dt / 1000; - } - } - else - { - MP_THREAD_GIL_EXIT(); - Helios_msleep(ms); - MP_THREAD_GIL_ENTER(); - } + mp_uint_t dt = 0; + mp_uint_t t0 = 0, t1 = 0; + Helios_Thread_t taskid = 0; + extern Helios_Thread_t ql_micropython_task_ref; + taskid = Helios_Thread_GetID(); + mp_uint_t qpy_mthread_sleep_deal_fun(mp_uint_t ms); + + if (ql_micropython_task_ref == taskid) { + for (;;) + { + t0 = mp_hal_ticks_us(); + MP_THREAD_GIL_EXIT(); + mp_uint_t wait_time = qpy_mthread_sleep_deal_fun(ms); + MP_THREAD_GIL_ENTER(); + if (wait_time >= ms) { + return; + } + MICROPY_EVENT_POLL_HOOK; + t1 = mp_hal_ticks_us(); + dt = t1 - t0; + if (dt / 1000 >= ms) { + return; + } + ms -= dt / 1000; + } + } else { + MP_THREAD_GIL_EXIT(); + Helios_msleep(ms); + MP_THREAD_GIL_ENTER(); + } } void mp_hal_delay_us(mp_uint_t us) { - mp_uint_t ms = us / 1000; + mp_uint_t ms = us / 1000; ms = ms ? ms : 1; - mp_hal_delay_ms(ms); + mp_hal_delay_ms(ms); } mp_uint_t mp_hal_ticks_cpu(void) { @@ -279,51 +261,42 @@ uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { return ret; } -mp_uint_t qpy_mthread_sleep_deal_fun(mp_uint_t ms) -{ - if(mp_mthread_sleep_deal_is_inited()) - { - mp_uint_t dt; - mp_uint_t t0 = mp_hal_ticks_us(); - int ret = mp_mthread_sleep(ms); - if(ret < 0) - { - return ms; - } - else - { - mp_uint_t t1 = mp_hal_ticks_us(); - dt = t1 - t0; - return dt / 1000; - } - } - else - { - Helios_msleep(ms); - return ms; - } +mp_uint_t qpy_mthread_sleep_deal_fun(mp_uint_t ms) { + if (mp_mthread_sleep_deal_is_inited()) { + mp_uint_t dt; + mp_uint_t t0 = mp_hal_ticks_us(); + int ret = mp_mthread_sleep(ms); + if (ret < 0) { + return ms; + } else { + mp_uint_t t1 = mp_hal_ticks_us(); + dt = t1 - t0; + return dt / 1000; + } + } else { + Helios_msleep(ms); + return ms; + } } -//mia.zhong @20220308 fix input of multi thread dump problem. -void _add_list_node() -{ +// mia.zhong @20220308 fix input of multi thread dump problem. +void _add_list_node() { Input_ListNode_t *node = (Input_ListNode_t *)malloc(sizeof(Input_ListNode_t)); memset(node, 0, sizeof(Input_ListNode_t)); - - if(0 == node->msg_q) { + + if (0 == node->msg_q) { node->msg_q = Helios_MsgQ_Create(QPY_MTHREAD_SLEEP_DEAL_MSG_MAX_NUM, sizeof(mp_uint_t)); } node->next_node = Head_node; Head_node = node; } -//mia.zhong @20220308 fix input of multi thread dump problem. -void _delete_list_node()//delete node -{ +// mia.zhong @20220308 fix input of multi thread dump problem. +void _delete_list_node() {// delete node Input_ListNode_t *node = NULL; if (Head_node) { - if(0 != Head_node->msg_q) { + if (0 != Head_node->msg_q) { Helios_MsgQ_Delete(Head_node->msg_q); } node = Head_node; @@ -336,15 +309,13 @@ void _delete_list_node()//delete node } } -void mp_mthread_sleep_deal_init(void) -{ - if(0 == qpy_mthread_sleep_queue) { +void mp_mthread_sleep_deal_init(void) { + if (0 == qpy_mthread_sleep_queue) { qpy_mthread_sleep_queue = \ - Helios_MsgQ_Create(QPY_MTHREAD_SLEEP_DEAL_MSG_MAX_NUM, sizeof(mp_uint_t)); + Helios_MsgQ_Create(QPY_MTHREAD_SLEEP_DEAL_MSG_MAX_NUM, sizeof(mp_uint_t)); } } -static bool mp_mthread_sleep_deal_is_inited(void) -{ - return (0 != qpy_mthread_sleep_queue); +static bool mp_mthread_sleep_deal_is_inited(void) { + return 0 != qpy_mthread_sleep_queue; } diff --git a/ports/quectel/mphalport.h b/ports/quectel/mphalport.h index 4eab86c586d9e..1c1e1b5eee800 100644 --- a/ports/quectel/mphalport.h +++ b/ports/quectel/mphalport.h @@ -30,14 +30,14 @@ #include "helios_os.h" #include "helios_uart.h" -#define HAL_TICK1S 32.768 +#define HAL_TICK1S 32.768 #define QPY_REPL_UART HELIOS_UART3 #define HELIOS_UART_BAUD HELIOS_UART_BAUD_115200 -//mia.zhong @20220308 input接口多线程调用导致dump问题 +// mia.zhong @20220308 input接口多线程调用导致dump问题 typedef struct Input_ListNode { - //int id; + // int id; int mthread_sleep_flag; Helios_MsgQ_t msg_q; void *next_node; diff --git a/ports/quectel/mpthreadport.c b/ports/quectel/mpthreadport.c index 98073b6994b75..f33ff7301e7e2 100644 --- a/ports/quectel/mpthreadport.c +++ b/ports/quectel/mpthreadport.c @@ -127,15 +127,15 @@ static void thread_entry(void *arg) { if (ext_thread_entry) { ext_thread_entry(arg); } - _vPortCleanUpTCB((void*)Helios_Thread_GetID()); + _vPortCleanUpTCB((void *)Helios_Thread_GetID()); Helios_Thread_Exit(); } int mp_thread_create_ex(void *(*entry)(void *), void *arg, size_t *stack_size, int priority, char *name) { // store thread entry function into a global variable so we can access it - ext_thread_entry = entry; - if (*stack_size == 0) { + ext_thread_entry = entry; + if (*stack_size == 0) { *stack_size = MP_THREAD_DEFAULT_STACK_SIZE; // default stack size } else if (*stack_size < MP_THREAD_MIN_STACK_SIZE) { *stack_size = MP_THREAD_MIN_STACK_SIZE; // minimum stack size @@ -155,11 +155,10 @@ int mp_thread_create_ex(void *(*entry)(void *), void *arg, size_t *stack_size, i .argv = arg }; Helios_Thread_t thread_id = Helios_Thread_Create(&ThreadAttr); - if(thread_id == 0) - { - mp_thread_mutex_unlock(&thread_mutex); - mp_raise_msg(&mp_type_OSError, (mp_rom_error_text_t)"can't create thread"); - } + if (thread_id == 0) { + mp_thread_mutex_unlock(&thread_mutex); + mp_raise_msg(&mp_type_OSError, (mp_rom_error_text_t)"can't create thread"); + } // add thread to linked list of all threads th->id = thread_id; @@ -167,7 +166,7 @@ int mp_thread_create_ex(void *(*entry)(void *), void *arg, size_t *stack_size, i th->arg = arg; th->stack = Helios_Thread_GetStaskPtr(th->id); - //stack_len must be 1/4 of ThreadAttr.stack_size + // stack_len must be 1/4 of ThreadAttr.stack_size th->stack_len = ThreadAttr.stack_size / sizeof(uint32_t); th->next = thread; thread = th; @@ -177,10 +176,10 @@ int mp_thread_create_ex(void *(*entry)(void *), void *arg, size_t *stack_size, i mp_thread_mutex_unlock(&thread_mutex); - return (int)th;//return task_node + return (int)th;// return task_node } -//forrest.liu@20210408 increase the priority for that python thread can,t be scheduled +// forrest.liu@20210408 increase the priority for that python thread can,t be scheduled mp_uint_t mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) { int th_node = mp_thread_create_ex(entry, arg, stack_size, (MP_THREAD_PRIORITY - 1), "mp_thread"); return th_node; @@ -194,7 +193,7 @@ void mp_new_thread_add(uint32_t th_id, uint32_t stack_size) { th->ready = 0; th->arg = NULL; th->stack = Helios_Thread_GetStaskPtr((Helios_Thread_t)th->id); - + th->stack_len = stack_size / sizeof(uint32_t); th->next = thread; thread = th; @@ -225,11 +224,11 @@ bool mp_thread_finish_by_threadid(int thread_id) { } bool mp_is_python_thread(void) { - Helios_Thread_t curr_id = Helios_Thread_GetID(); + Helios_Thread_t curr_id = Helios_Thread_GetID(); mp_thread_mutex_lock(&thread_mutex, 1); for (thread_t *th = thread; th != NULL; th = th->next) { if (th->id == curr_id) { - mp_thread_mutex_unlock(&thread_mutex); + mp_thread_mutex_unlock(&thread_mutex); return true; } } @@ -238,7 +237,7 @@ bool mp_is_python_thread(void) { } int mp_thread_get_current_tsknode(void) { - Helios_Thread_t curr_id = Helios_Thread_GetID(); + Helios_Thread_t curr_id = Helios_Thread_GetID(); mp_thread_mutex_lock(&thread_mutex, 1); for (thread_t *th = thread; th != NULL; th = th->next) { if (th->id == (Helios_Thread_t)curr_id) { @@ -279,7 +278,7 @@ void mp_thread_mutex_unlock(mp_thread_mutex_t *mutex) { Helios_Mutex_Unlock(*mutex); } -//Added by Freddy @20210818 delete a lock +// Added by Freddy @20210818 delete a lock void mp_thread_mutex_del(mp_thread_mutex_t *mutex) { Helios_Mutex_Delete(*mutex); } @@ -320,14 +319,14 @@ void mp_thread_deinit(void) { } else { // Call qpy_thread_delete to delete the task (it will call vPortCleanUpTCB) Helios_Thread_Delete(id); - _vPortCleanUpTCB((void*)id); + _vPortCleanUpTCB((void *)id); } } } -unsigned int mp_get_available_memory_size(void) -{ +unsigned int mp_get_available_memory_size(void) { return Helios_GetAvailableMemorySize(); } + #endif // MICROPY_PY_THREAD From 3c04938b1c8202c7d4f7b77f8e025ed80ca5a013 Mon Sep 17 00:00:00 2001 From: Nikola Neskovic Date: Mon, 9 Mar 2026 16:27:27 +0100 Subject: [PATCH 04/13] ports/quectel: Boards features fix. --- ports/quectel/boards/EC600UCN_LB/board.json | 6 +----- ports/quectel/boards/EG915UEC_AC/board.json | 6 +----- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/ports/quectel/boards/EC600UCN_LB/board.json b/ports/quectel/boards/EC600UCN_LB/board.json index 3edacaf108c01..0aabf37d25262 100644 --- a/ports/quectel/boards/EC600UCN_LB/board.json +++ b/ports/quectel/boards/EC600UCN_LB/board.json @@ -3,11 +3,7 @@ "../deploy.md" ], "docs": "", - "features": [ - "Celluar network", - "bsp", - "USB" - ], + "features": [], "images": [ "ec600ucn_lb.jpg" ], diff --git a/ports/quectel/boards/EG915UEC_AC/board.json b/ports/quectel/boards/EG915UEC_AC/board.json index 24894487c2793..aac840787d6b5 100644 --- a/ports/quectel/boards/EG915UEC_AC/board.json +++ b/ports/quectel/boards/EG915UEC_AC/board.json @@ -3,11 +3,7 @@ "../deploy.md" ], "docs": "", - "features": [ - "Celluar network", - "bsp", - "USB" - ], + "features": [], "images": [ "eg915uec_ac.jpg" ], From 51734840033c0a102dae5e35526b4701fce9b05d Mon Sep 17 00:00:00 2001 From: Nikola Neskovic Date: Mon, 9 Mar 2026 17:05:47 +0100 Subject: [PATCH 05/13] ports/quectel: Update boot and manifest. --- ports/quectel/boards/manifest.py | 2 -- ports/quectel/modules/_boot.py | 42 +++++++++++++++---------------- ports/quectel/modules/manifest.py | 1 + ports/quectel/modules/modules.py | 1 - ports/quectel/quectel.mk | 2 +- 5 files changed, 22 insertions(+), 26 deletions(-) delete mode 100644 ports/quectel/boards/manifest.py create mode 100644 ports/quectel/modules/manifest.py delete mode 100644 ports/quectel/modules/modules.py diff --git a/ports/quectel/boards/manifest.py b/ports/quectel/boards/manifest.py deleted file mode 100644 index b0b0d31a051b1..0000000000000 --- a/ports/quectel/boards/manifest.py +++ /dev/null @@ -1,2 +0,0 @@ -freeze("$(PORT_DIR)/modules") -include("$(MPY_DIR)/extmod/asyncio") diff --git a/ports/quectel/modules/_boot.py b/ports/quectel/modules/_boot.py index 2352f9c4f7949..1a997f70aed97 100644 --- a/ports/quectel/modules/_boot.py +++ b/ports/quectel/modules/_boot.py @@ -1,11 +1,11 @@ # Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. -# +# # 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. @@ -15,54 +15,52 @@ import uos import ujson -''' +""" Mark.Zhu - 2022/12/02 Added the littlefs2 mount function,it will be called after a failed attempt to mount littlefs1 -''' +""" # global datacall_flag datacall_flag = 1 + def _repl_enable(): global datacall_flag if "system_config.json" in uos.listdir("/"): - with open("/system_config.json", "r", encoding='utf-8') as fd: + with open("/system_config.json", "r", encoding="utf-8") as fd: try: json_data = ujson.load(fd) datacall_flag = json_data.get("datacallFlag", 1) - except ValueError: - with open("/usr/system_config.json", "w", encoding='utf-8') as fdw: + with open("/usr/system_config.json", "w", encoding="utf-8") as fdw: new_json_data = ujson.dumps({"replFlag": 0, "datacallFlag": datacall_flag}) fdw.write(new_json_data) else: - with open("/system_config.json", "w+", encoding='utf-8') as fd: + with open("/system_config.json", "w+", encoding="utf-8") as fd: repl_data = ujson.dumps({"replFlag": 0}) fd.write(repl_data) -try: + +try: udev = None try: from uos import VfsLfs1 as VfsLfs except Exception: from uos import VfsLfs2 as VfsLfs - udev = uos.FlashDevice('customer_fs', 4096) + udev = uos.FlashDevice("customer_fs", 4096) try: - uos.mount(udev, '/') + uos.mount(udev, "/") except Exception as e: - if 'ENODEV' in str(e): + if "ENODEV" in str(e): VfsLfs.mkfs(udev) - uos.mount(udev, '/') - else: - raise ValueError("LFS usr mount fail".format(e)) - if 'usr' not in uos.listdir(): - uos.mkdir('usr') - if 'bak' not in uos.listdir(): - uos.mkdir('bak') - + uos.mount(udev, "/") + if "usr" not in uos.listdir(): + uos.mkdir("usr") + if "bak" not in uos.listdir(): + uos.mkdir("bak") except Exception: - print('error occurs in boot step.') + print("error occurs in boot step.") finally: _repl_enable() diff --git a/ports/quectel/modules/manifest.py b/ports/quectel/modules/manifest.py new file mode 100644 index 0000000000000..c80309cf675a2 --- /dev/null +++ b/ports/quectel/modules/manifest.py @@ -0,0 +1 @@ +freeze("$(PORT_DIR)/modules") diff --git a/ports/quectel/modules/modules.py b/ports/quectel/modules/modules.py deleted file mode 100644 index 9293530d2f221..0000000000000 --- a/ports/quectel/modules/modules.py +++ /dev/null @@ -1 +0,0 @@ -freeze_as_mpy(".", "_boot.py") diff --git a/ports/quectel/quectel.mk b/ports/quectel/quectel.mk index acd63236c1f02..96774d7170cea 100644 --- a/ports/quectel/quectel.mk +++ b/ports/quectel/quectel.mk @@ -83,4 +83,4 @@ QUEC_SRC_MOD += \ modhelios.c # py modules define -QUEC_PY_MOD = modules/modules.py +QUEC_PY_MOD = modules/manifest.py From 48bcf95092199d966e83844a3593009d1cf95dc5 Mon Sep 17 00:00:00 2001 From: Nikola Neskovic Date: Fri, 20 Mar 2026 15:48:17 +0100 Subject: [PATCH 06/13] quectel: Added helios sdk path. --- ports/quectel/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ports/quectel/Makefile b/ports/quectel/Makefile index eed5684fb46ee..ffd7ee8fe11d8 100644 --- a/ports/quectel/Makefile +++ b/ports/quectel/Makefile @@ -1,5 +1,9 @@ TOP := ../.. +ifneq ($(HeliosSDK_PATH),) +ROOT := $(HeliosSDK_PATH) +else ROOT := $(TOP)/../.. +endif include ../../py/mkenv.mk include mpconfigport.mk From d0479e7aa7a419d4d5d6e854d1f1694a85886074 Mon Sep 17 00:00:00 2001 From: Nikola Neskovic Date: Fri, 20 Mar 2026 15:50:17 +0100 Subject: [PATCH 07/13] quectel: Rename uos to os. --- ports/quectel/modules/_boot.py | 22 +++++++++++----------- ports/quectel/moduos.c | 12 ++++++------ 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/ports/quectel/modules/_boot.py b/ports/quectel/modules/_boot.py index 1a997f70aed97..25893d5f4ba8a 100644 --- a/ports/quectel/modules/_boot.py +++ b/ports/quectel/modules/_boot.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -import uos +import os import ujson """ @@ -25,7 +25,7 @@ def _repl_enable(): global datacall_flag - if "system_config.json" in uos.listdir("/"): + if "system_config.json" in os.listdir("/"): with open("/system_config.json", "r", encoding="utf-8") as fd: try: json_data = ujson.load(fd) @@ -43,21 +43,21 @@ def _repl_enable(): try: udev = None try: - from uos import VfsLfs1 as VfsLfs + from os import VfsLfs1 as VfsLfs except Exception: - from uos import VfsLfs2 as VfsLfs + from os import VfsLfs2 as VfsLfs - udev = uos.FlashDevice("customer_fs", 4096) + udev = os.FlashDevice("customer_fs", 4096) try: - uos.mount(udev, "/") + os.mount(udev, "/") except Exception as e: if "ENODEV" in str(e): VfsLfs.mkfs(udev) - uos.mount(udev, "/") - if "usr" not in uos.listdir(): - uos.mkdir("usr") - if "bak" not in uos.listdir(): - uos.mkdir("bak") + os.mount(udev, "/") + if "usr" not in os.listdir(): + os.mkdir("usr") + if "bak" not in os.listdir(): + os.mkdir("bak") except Exception: print("error occurs in boot step.") diff --git a/ports/quectel/moduos.c b/ports/quectel/moduos.c index bece7c6021da0..3d79fd533e060 100644 --- a/ports/quectel/moduos.c +++ b/ports/quectel/moduos.c @@ -40,7 +40,7 @@ #include "vfs_quecfs.h" #endif -#if MICROPY_QPY_MODULE_UOS +#if MICROPY_QPY_MODULE_OS static char sysname[30] = {0}; static char nodename[20] = {0}; @@ -150,7 +150,7 @@ static MP_DEFINE_CONST_FUN_OBJ_0(os_urandom___init___obj, os_urandom___init__); static mp_obj_t os_dupterm_notify(mp_obj_t obj_in) { (void)obj_in; for (;;) { - int c = mp_uos_dupterm_rx_chr(); + int c = mp_os_dupterm_rx_chr(); if (c < 0) { break; } @@ -163,14 +163,14 @@ static MP_DEFINE_CONST_FUN_OBJ_1(os_dupterm_notify_obj, os_dupterm_notify); extern const mp_obj_type_t helios_flash_device_type; 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___name__), MP_ROM_QSTR(MP_QSTR_os) }, #if OS_URANDOM_SEED_ON_IMPORT { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&os_urandom___init___obj) }, #endif { MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&os_uname_obj) }, { MP_ROM_QSTR(MP_QSTR_uname2), MP_ROM_PTR(&os_uname2_obj) }, #if MICROPY_PY_OS_DUPTERM - { MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&mp_uos_dupterm_obj) }, + { MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&mp_os_dupterm_obj) }, { MP_ROM_QSTR(MP_QSTR_dupterm_notify), MP_ROM_PTR(&os_dupterm_notify_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_FlashDevice), MP_ROM_PTR(&helios_flash_device_type) }, @@ -217,10 +217,10 @@ static const mp_rom_map_elem_t os_module_globals_table[] = { static MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table); -const mp_obj_module_t uos_module = { +const mp_obj_module_t os_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t *)&os_module_globals, }; -MP_REGISTER_MODULE(MP_QSTR_uos, uos_module); +MP_REGISTER_MODULE(MP_QSTR_os, os_module); #endif From 2faf9b4a95299e4c3a9e955bc3da1fdb8904526b Mon Sep 17 00:00:00 2001 From: Nikola Neskovic Date: Fri, 20 Mar 2026 15:56:41 +0100 Subject: [PATCH 08/13] quectel: Make mpy-cross host dependant. --- ports/quectel/Makefile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ports/quectel/Makefile b/ports/quectel/Makefile index ffd7ee8fe11d8..2855e14c34884 100644 --- a/ports/quectel/Makefile +++ b/ports/quectel/Makefile @@ -30,7 +30,12 @@ MICROPY_ROM_TEXT_COMPRESSION ?= 1 FROZEN_MANIFEST = $(QUEC_PY_MOD) +ifeq ($(OS),Windows_NT) export MICROPY_MPYCROSS = $(TOP)/mpy-cross/build/mpy-cross.exe +else +export MICROPY_MPYCROSS = $(TOP)/mpy-cross/build/mpy-cross +endif + # include py core make definitions include $(TOP)/py/py.mk include $(TOP)/extmod/extmod.mk From 6ebc2402e9b11ec4ffc99d3f6939d5fa4772516b Mon Sep 17 00:00:00 2001 From: Nikola Neskovic Date: Thu, 26 Mar 2026 11:50:06 +0100 Subject: [PATCH 09/13] quectel: Switch to extmod/modos. --- ports/quectel/Makefile | 3 +- ports/quectel/modflashdev.c | 58 +++++---- ports/quectel/modules/_boot.py | 13 +- ports/quectel/moduos.c | 226 --------------------------------- ports/quectel/mpconfigport.h | 4 +- ports/quectel/quectel.mk | 1 - 6 files changed, 46 insertions(+), 259 deletions(-) delete mode 100644 ports/quectel/moduos.c diff --git a/ports/quectel/Makefile b/ports/quectel/Makefile index 2855e14c34884..e192abf5248c6 100644 --- a/ports/quectel/Makefile +++ b/ports/quectel/Makefile @@ -86,7 +86,8 @@ EXTMOD_SRC_C = extmod/vfs.c \ extmod/vfs_reader.c \ extmod/modre.c \ extmod/modhashlib.c \ - extmod/moductypes.c + extmod/moductypes.c \ + extmod/modos.c EXTMOD_SRC_C += $(SRC_THIRDPARTY_C) diff --git a/ports/quectel/modflashdev.c b/ports/quectel/modflashdev.c index 2047e600414ce..4a9ea8f7f8d9e 100644 --- a/ports/quectel/modflashdev.c +++ b/ports/quectel/modflashdev.c @@ -35,7 +35,7 @@ #define MOD_FLASHDEV_LOG(msg, ...) custom_log('flashdev', msg,##__VA_ARGS__) -const mp_obj_type_t helios_flash_device_type; +const mp_obj_type_t flash_device_type; struct lfs_flash_info { @@ -44,17 +44,17 @@ struct lfs_flash_info uint32_t LfsEndAddress; }; -typedef struct _helios_flash_device_obj_t { +typedef struct flash_device_obj_t { mp_obj_base_t base; int block_size; int block_count; struct lfs_flash_info info; char partition_name[32]; -} helios_flash_device_obj_t; +} flash_device_obj_t; -static mp_obj_t helios_flash_device_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 flash_init(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, 2, false); - helios_flash_device_obj_t *self = mp_obj_malloc(helios_flash_device_obj_t, type); + flash_device_obj_t *self = mp_obj_malloc(flash_device_obj_t, type); mp_buffer_info_t bufinfo; memset(self->partition_name, 0x0, sizeof(self->partition_name)); @@ -91,8 +91,8 @@ static mp_obj_t helios_flash_device_make_new(const mp_obj_type_t *type, size_t n return MP_OBJ_FROM_PTR(self); } -static mp_obj_t helios_flash_device_readblocks(size_t n_args, const mp_obj_t *args) { - helios_flash_device_obj_t *self = MP_OBJ_TO_PTR(args[0]); +static mp_obj_t flash_readblocks(size_t n_args, const mp_obj_t *args) { + flash_device_obj_t *self = MP_OBJ_TO_PTR(args[0]); uint32_t FlashAddrss = 0; uint32_t block_num = mp_obj_get_int(args[1]); uint32_t offset = block_num * self->block_size; @@ -108,10 +108,10 @@ static mp_obj_t helios_flash_device_readblocks(size_t n_args, const mp_obj_t *ar ret = Helios_Flash_Read((uint32_t)FlashAddrss, bufinfo.buf, bufinfo.len); return MP_OBJ_NEW_SMALL_INT(ret); } -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(helios_flash_device_readblocks_obj, 3, 4, helios_flash_device_readblocks); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(flash_readblocks_obj, 3, 4, flash_readblocks); -static mp_obj_t helios_flash_device_writeblocks(size_t n_args, const mp_obj_t *args) { - helios_flash_device_obj_t *self = MP_OBJ_TO_PTR(args[0]); +static mp_obj_t flash_writeblocks(size_t n_args, const mp_obj_t *args) { + flash_device_obj_t *self = MP_OBJ_TO_PTR(args[0]); uint32_t block_num = mp_obj_get_int(args[1]); uint32_t offset = block_num * self->block_size; mp_buffer_info_t bufinfo; @@ -131,10 +131,10 @@ static mp_obj_t helios_flash_device_writeblocks(size_t n_args, const mp_obj_t *a ret = Helios_Flash_Write(FlashAddrss, bufinfo.buf, bufinfo.len); return MP_OBJ_NEW_SMALL_INT(ret); } -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(helios_flash_device_writeblocks_obj, 3, 4, helios_flash_device_writeblocks); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(flash_writeblocks_obj, 3, 4, flash_writeblocks); -static mp_obj_t helios_flash_device_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t arg_in) { - helios_flash_device_obj_t *self = self_in; +static mp_obj_t flash_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t arg_in) { + flash_device_obj_t *self = self_in; mp_int_t cmd = mp_obj_get_int(cmd_in); mp_int_t block_num = mp_obj_get_int(arg_in); int ret; @@ -161,19 +161,31 @@ static mp_obj_t helios_flash_device_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_ return MP_OBJ_NEW_SMALL_INT(-1); } } -static MP_DEFINE_CONST_FUN_OBJ_3(helios_flash_device_ioctl_obj, helios_flash_device_ioctl); +static MP_DEFINE_CONST_FUN_OBJ_3(flash_ioctl_obj, flash_ioctl); -static const mp_rom_map_elem_t helios_flash_device_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&helios_flash_device_readblocks_obj) }, - { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&helios_flash_device_writeblocks_obj) }, - { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&helios_flash_device_ioctl_obj) }, -}; -static MP_DEFINE_CONST_DICT(helios_flash_device_locals_dict, helios_flash_device_locals_dict_table); +static const mp_obj_dict_t flash_device_locals_dict; MP_DEFINE_CONST_OBJ_TYPE( - helios_flash_device_type, + flash_device_type, MP_QSTR_FlashDevice, MP_TYPE_FLAG_NONE, - make_new, helios_flash_device_make_new, - locals_dict, &helios_flash_device_locals_dict + make_new, flash_init, + locals_dict, &flash_device_locals_dict ); + +static const mp_rom_map_elem_t flash_device_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_myflash) }, + { MP_ROM_QSTR(MP_QSTR_FlashDevice), MP_ROM_PTR(&flash_device_type)}, + { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&flash_readblocks_obj) }, + { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&flash_writeblocks_obj) }, + { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&flash_ioctl_obj) }, +}; + +static MP_DEFINE_CONST_DICT(flash_device_locals_dict, flash_device_locals_dict_table); + +const mp_obj_module_t flashdev_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&flash_device_locals_dict, +}; + +MP_REGISTER_MODULE(MP_QSTR_flashdev, flashdev_module); diff --git a/ports/quectel/modules/_boot.py b/ports/quectel/modules/_boot.py index 25893d5f4ba8a..22b8e85164ba7 100644 --- a/ports/quectel/modules/_boot.py +++ b/ports/quectel/modules/_boot.py @@ -14,6 +14,7 @@ import os import ujson +import flashdev """ Mark.Zhu - 2022/12/02 @@ -46,14 +47,14 @@ def _repl_enable(): from os import VfsLfs1 as VfsLfs except Exception: from os import VfsLfs2 as VfsLfs - - udev = os.FlashDevice("customer_fs", 4096) + dev = flashdev.FlashDevice("customer_fs", 4096) try: + udev = os.VfsLfs2(dev) + os.mount(udev, "/") + except Exception: + os.VfsLfs2.mkfs(dev) + udev = os.VfsLfs2(dev) os.mount(udev, "/") - except Exception as e: - if "ENODEV" in str(e): - VfsLfs.mkfs(udev) - os.mount(udev, "/") if "usr" not in os.listdir(): os.mkdir("usr") if "bak" not in os.listdir(): diff --git a/ports/quectel/moduos.c b/ports/quectel/moduos.c deleted file mode 100644 index 3d79fd533e060..0000000000000 --- a/ports/quectel/moduos.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020-2021 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/objstr.h" -#include "py/runtime.h" -#include "py/mperrno.h" -#include "py/mphal.h" -#include "extmod/misc.h" -#include "extmod/vfs.h" -#include "extmod/vfs_lfs.h" -#include "mpversion.h" -#include "helios_dev.h" -#if MICROPY_VFS_QUECFS -#include "vfs_quecfs.h" -#endif - -#if MICROPY_QPY_MODULE_OS - -static char sysname[30] = {0}; -static char nodename[20] = {0}; -static char machine[30] = {0}; - -extern const mp_obj_type_t mp_fat_vfs_type; - - -static const qstr os_uname_info_fields[] = { - MP_QSTR_sysname, MP_QSTR_nodename, MP_QSTR_release, - MP_QSTR_version, MP_QSTR_machine, MP_QSTR_qpyver, -}; - -static MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, sysname); -static MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, nodename); -static MP_DEFINE_STR_OBJ(os_uname_info_release_obj, MICROPY_VERSION_STRING); -static MP_DEFINE_STR_OBJ(os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE); -static MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, machine); -static MP_DEFINE_STR_OBJ(os_uname_info_qpyver_obj, QUECPYTHON_VERSION_STRING); - -static MP_DEFINE_ATTRTUPLE( - os_uname_info_obj, - os_uname_info_fields, - 6, - (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, - (mp_obj_t)&os_uname_info_qpyver_obj - ); - -static mp_obj_t os_uname2(void) { - Helios_Dev_GetProductName((void *)sysname, sizeof(sysname)); - Helios_Dev_GetModel((void *)nodename, sizeof(nodename)); - snprintf(machine, sizeof(machine), "%s with QUECTEL", nodename); - - os_uname_info_sysname_obj.len = strlen(sysname); - os_uname_info_nodename_obj.len = strlen(nodename); - os_uname_info_machine_obj.len = strlen(machine); - os_uname_info_qpyver_obj.len = strlen(QUECPYTHON_VERSION_STRING); - return (mp_obj_t)&os_uname_info_obj; -} -static MP_DEFINE_CONST_FUN_OBJ_0(os_uname2_obj, os_uname2); - - -static mp_obj_t os_uname(void) { - char sysname[40] = {0}; - char nodname[20] = {0}; - char release[20] = {0}; - char machine[30] = {0}; - char version[128] = {0}; - // char qpy_ver[20] = {0}; - - char mob_usb_product[64] = {0}; - char mob_model_id[64] = {0}; - // char _qpy_ver[20] = {0}; - - Helios_Dev_GetProductName((void *)mob_usb_product, sizeof(mob_usb_product)); - Helios_Dev_GetModel((void *)mob_model_id, sizeof(mob_model_id)); - // Helios_Dev_GetQpyVersion((void *)_qpy_ver, sizeof(_qpy_ver)); - - snprintf(sysname, sizeof(sysname), "sysname=%s", mob_usb_product); - snprintf(nodname, sizeof(nodname), "nodename=%s", mob_model_id); - snprintf(release, sizeof(release), "release=%s", MICROPY_VERSION_STRING); - snprintf(version, sizeof(version), "version=%s on %s", MICROPY_GIT_TAG, MICROPY_BUILD_DATE); - snprintf(machine, sizeof(machine), "machine=%s with QUECTEL", mob_model_id); - // snprintf(qpy_ver, sizeof(qpy_ver), "qpyver=%s", _qpy_ver); - - mp_obj_t tuple[6] = { - mp_obj_new_str(sysname, strlen(sysname)), - mp_obj_new_str(nodname, strlen(nodname)), - mp_obj_new_str(release, strlen(release)), - mp_obj_new_str(version, strlen(version)), - mp_obj_new_str(machine, strlen(machine)), - mp_obj_new_str("qpyver="QUECPYTHON_VERSION_STRING, strlen("qpyver="QUECPYTHON_VERSION_STRING)), - }; - - return mp_obj_new_tuple(6, tuple); -} - -static MP_DEFINE_CONST_FUN_OBJ_0(os_uname_obj, os_uname); - -// 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 OS_URANDOM_SEED_ON_IMPORT (1) -#else -#define OS_URANDOM_SEED_ON_IMPORT (0) -#endif - -#if OS_URANDOM_SEED_ON_IMPORT -static mp_obj_t os_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; - srand(MICROPY_PY_URANDOM_SEED_INIT_FUNC); - } - return mp_const_none; - -} -static MP_DEFINE_CONST_FUN_OBJ_0(os_urandom___init___obj, os_urandom___init__); -#endif - -#if MICROPY_PY_OS_DUPTERM -static mp_obj_t 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(os_dupterm_notify_obj, os_dupterm_notify); -#endif - -extern const mp_obj_type_t helios_flash_device_type; -static const mp_rom_map_elem_t os_module_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_os) }, - #if OS_URANDOM_SEED_ON_IMPORT - { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&os_urandom___init___obj) }, - #endif - { MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&os_uname_obj) }, - { MP_ROM_QSTR(MP_QSTR_uname2), MP_ROM_PTR(&os_uname2_obj) }, - #if MICROPY_PY_OS_DUPTERM - { MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&mp_os_dupterm_obj) }, - { MP_ROM_QSTR(MP_QSTR_dupterm_notify), MP_ROM_PTR(&os_dupterm_notify_obj) }, - #endif - { MP_ROM_QSTR(MP_QSTR_FlashDevice), MP_ROM_PTR(&helios_flash_device_type) }, - #if MICROPY_VFS - { 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_rmdir), MP_ROM_PTR(&mp_vfs_rmdir_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_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_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_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 defined(PLAT_Qualcomm) - { MP_ROM_QSTR(MP_QSTR_VfsEfs), MP_ROM_PTR(&mp_type_vfs_efs) }, - #endif - #if defined(PLAT_Unisoc_8910_R05) || defined(PLAT_Unisoc_8910_R06) - { MP_ROM_QSTR(MP_QSTR_VfsTemp), MP_ROM_PTR(&mp_type_vfs_temp) }, - #endif - #if defined(PLAT_Unisoc_8910_R05) || defined(PLAT_Unisoc_8910_R06) || (defined(PLAT_Unisoc_8850_R02) && !defined(BOARD_EC800GCN_LD_XBND)) - { MP_ROM_QSTR(MP_QSTR_VfsSd), MP_ROM_PTR(&mp_type_vfs_temp) }, - #endif - #if MICROPY_VFS_FAT_SDIO - { MP_ROM_QSTR(MP_QSTR_VfsEmmc), MP_ROM_PTR(&mp_type_vfs_sdio_emmc) }, - { MP_ROM_QSTR(MP_QSTR_VfsSd), MP_ROM_PTR(&mp_type_vfs_sdio_sd) }, - #endif - #if MICROPY_VFS_QUECFS - { MP_ROM_QSTR(MP_QSTR_VfsQuecfs), MP_ROM_PTR(&mp_type_vfs_quecfs) }, - #endif - #endif -}; - -static MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table); - -const mp_obj_module_t os_module = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t *)&os_module_globals, -}; - -MP_REGISTER_MODULE(MP_QSTR_os, os_module); -#endif diff --git a/ports/quectel/mpconfigport.h b/ports/quectel/mpconfigport.h index 7d11368ef1b95..f0f558c120b05 100644 --- a/ports/quectel/mpconfigport.h +++ b/ports/quectel/mpconfigport.h @@ -44,11 +44,11 @@ #define MICROPY_PY_IO (1) #define MICROPY_PY_JSON (1) #define MICROPY_VFS (1) -#define MICROPY_QPY_MODULE_UOS (1) +#define MICROPY_QPY_MODULE_UOS (0) #define MICROPY_PY_VFS (0) #define MICROPY_PY_TIME (0) #define MICROPY_PY_HEAPQ (0) -#define MICROPY_PY_OS (0) +#define MICROPY_PY_OS (1) #define MICROPY_PY_PLATFORM (0) #define MICROPY_PY_SELECT (0) #define MICROPY_PY_FRAMEBUF (0) diff --git a/ports/quectel/quectel.mk b/ports/quectel/quectel.mk index 96774d7170cea..dd11e06fed431 100644 --- a/ports/quectel/quectel.mk +++ b/ports/quectel/quectel.mk @@ -78,7 +78,6 @@ QUEC_SRC += \ # modules source file will used by gen QUEC_SRC_MOD += \ gccollect.c \ - moduos.c \ modflashdev.c \ modhelios.c From 5161eb2353273abe4236b24e579858b650e802f6 Mon Sep 17 00:00:00 2001 From: Nikola Neskovic Date: Fri, 3 Apr 2026 09:27:19 +0200 Subject: [PATCH 10/13] quectel: Clean mpconfigport and makefiles. --- ports/quectel/Makefile | 24 ++--- ports/quectel/mpconfigport.h | 160 +++++++++------------------------- ports/quectel/mpconfigport.mk | 21 ----- ports/quectel/quectel.mk | 14 --- 4 files changed, 45 insertions(+), 174 deletions(-) delete mode 100644 ports/quectel/mpconfigport.mk diff --git a/ports/quectel/Makefile b/ports/quectel/Makefile index e192abf5248c6..95f02bec6579e 100644 --- a/ports/quectel/Makefile +++ b/ports/quectel/Makefile @@ -6,7 +6,6 @@ ROOT := $(TOP)/../.. endif include ../../py/mkenv.mk -include mpconfigport.mk include quectel.mk CROSS = 1 @@ -27,7 +26,6 @@ QSTR_DEFS = qstrdefsport.h # MicroPython feature configurations MICROPY_ROM_TEXT_COMPRESSION ?= 1 - FROZEN_MANIFEST = $(QUEC_PY_MOD) ifeq ($(OS),Windows_NT) @@ -66,7 +64,8 @@ CXXFLAGS += $(CXXFLAGS_MOD) CFLAGS += $(CFLAGS_MOD) LDFLAGS += $(LDFLAGS_MOD) -LIBS = +LIBS = lib/littlefs/lfs2.c \ + lib/littlefs/lfs2_util.c SHARED_SRC_C = shared/libc/printf.c \ shared/readline/readline.c \ @@ -77,31 +76,18 @@ SHARED_SRC_C = shared/libc/printf.c \ shared/runtime/interrupt_char.c \ shared/timeutils/timeutils.c -EXTMOD_SRC_C = extmod/vfs.c \ - extmod/vfs_lfs.c \ - extmod/vfs_blockdev.c \ - extmod/modrandom.c \ - extmod/modjson.c \ - extmod/modbinascii.c \ - extmod/vfs_reader.c \ - extmod/modre.c \ - extmod/modhashlib.c \ - extmod/moductypes.c \ - extmod/modos.c - -EXTMOD_SRC_C += $(SRC_THIRDPARTY_C) - SRC_MOD += $(QUEC_SRC_MOD) SRC_C += $(SRC_MOD) \ $(SHARED_SRC_C) \ - $(EXTMOD_SRC_C) \ + $(SRC_EXTMOD_C) \ + $(LIBS) \ $(QUEC_SRC) \ $(BUILD)/frozen_content.c SRC_CXX += $(SRC_MOD_CXX) -SRC_QSTR += $(SRC_MOD) $(SRC_MOD_CXX) $(SHARED_SRC_C) $(EXTMOD_SRC_C) +SRC_QSTR += $(SRC_MOD) $(SRC_MOD_CXX) $(SHARED_SRC_C) $(SRC_EXTMOD_C) OBJ += $(PY_CORE_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_CXX:.cpp=.o)) diff --git a/ports/quectel/mpconfigport.h b/ports/quectel/mpconfigport.h index f0f558c120b05..451e310381e49 100644 --- a/ports/quectel/mpconfigport.h +++ b/ports/quectel/mpconfigport.h @@ -31,8 +31,8 @@ /****************************** user define ************************************/ // python grammar #define MICROPY_PY_ATTRTUPLE (1) -#define MICROPY_PY_BUILTINS_BYTEARRAY (1) -#define MICROPY_CPYTHON_COMPAT (1) +#define MICROPY_PY_BUILTINS_BYTEARRAY (1) +#define MICROPY_CPYTHON_COMPAT (1) // builtin op #define MICROPY_PY_BUILTINS_STR_OP_MODULO (1) @@ -42,10 +42,10 @@ // modules #define MICROPY_PY_IO (1) -#define MICROPY_PY_JSON (1) +#define MICROPY_PY_JSON (1) #define MICROPY_VFS (1) -#define MICROPY_QPY_MODULE_UOS (0) #define MICROPY_PY_VFS (0) +#define MICROPY_VFS_LFS2 (1) #define MICROPY_PY_TIME (0) #define MICROPY_PY_HEAPQ (0) #define MICROPY_PY_OS (1) @@ -54,110 +54,53 @@ #define MICROPY_PY_FRAMEBUF (0) #define MICROPY_PY_ASYNCIO (0) #define MICROPY_PY_BINASCII_CRC32 (0) - -#define MICROPY_PY_UCTYPES (MICROPY_QPY_PY_UCTYPES) -#define MICROPY_PY_DEFLATE (0) - +#define MICROPY_PY_UCTYPES (0) +#define MICROPY_PY_DEFLATE (0) #define MICROPY_OPT_COMPUTED_GOTO (1) /******************************** base define **********************************/ // options to control how MicroPython is built - -// Use the minimal starting configuration (disables all optional features). #define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES) // You can disable the built-in MicroPython compiler by setting the following // config option to 0. If you do this then you won't get a REPL prompt, but you // will still be able to execute pre-compiled scripts, compiled with mpy-cross. -#define MICROPY_ENABLE_COMPILER (1) - -#define MICROPY_ENABLE_GC (1) -#define MICROPY_PY_GC (1) -#define MICROPY_HELPER_REPL (1) -#define MICROPY_ENABLE_EXTERNAL_IMPORT (1) -#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) -#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE) // decimal numbers support -#define MICROPY_USE_INTERNAL_PRINTF (0) -#define MPZ_DIG_SIZE (16) -#define MICROPY_PY_SYS (1) - -#define MICROPY_ALLOC_PATH_MAX (256) -#define MICROPY_ALLOC_PARSE_CHUNK_INIT (16) - -#define MICROPY_ERROR_REPORTING MICROPY_ERROR_REPORTING_NORMAL -#define MICROPY_USE_INTERNAL_ERRNO (1) -#define MICROPY_ENABLE_SCHEDULER (1) -#define MICROPY_SCHEDULER_STATIC_NODES (0) -#define MICROPY_SCHEDULER_DEPTH (64)// 8 -#define MICROPY_REPL_AUTO_INDENT (1) -#define MICROPY_PY_UTIME_MP_HAL (1) - - -#define MICROPY_PY_THREAD (1) -#define MICROPY_PY_THREAD_GIL (1) -#define MICROPY_ENABLE_CALLBACK_DEAL (0) -#define MICROPY_READER_VFS (1) - -#define MICROPY_KBD_EXCEPTION (1) -#define MICROPY_PY_SOFT_RESET (0) -#define MICROPY_PY_IO_FILEIO (1) -#define MICROPY_PY_BUILTINS_SLICE (1) -#define MICROPY_PY_BUILTINS_PROPERTY (1) -#define MICROPY_PY_BUILTINS_BYTEARRAY (1) -#define MICROPY_PY_BUILTINS_SET (1) -#define MICROPY_PY_BUILTINS_MEMORYVIEW (1) -#define MICROPY_PY_SYS_STDFILES (1) -#define MICROPY_PY_SYS_STDIO_BUFFER (1) -#define MICROPY_PY_STRUCT (1) -#define MICROPY_ENABLE_FINALISER (1) -#define MICROPY_PY_BUILTINS_ENUMERATE (1) -#define MICROPY_PY_BUILTINS_MIN_MAX (1) -#if defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) -#define MICROPY_PY_URANDOM (1) -#define MICROPY_PY_URANDOM_EXTRA_FUNCS (1) -#endif - -#define MICROPY_PERSISTENT_CODE_LOAD (1) -#define MICROPY_PY_MICROPYTHON (1) -#define MICROPY_PY_MICROPYTHON_MEM_INFO (1) +#define MICROPY_ENABLE_COMPILER (1) + +#define MICROPY_ENABLE_GC (1) +#define MICROPY_PY_GC (1) +#define MICROPY_HELPER_REPL (1) +#define MICROPY_ENABLE_EXTERNAL_IMPORT (1) +#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) +#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE) // decimal numbers support +#define MICROPY_USE_INTERNAL_PRINTF (0) +#define MPZ_DIG_SIZE (16) +#define MICROPY_PY_SYS (1) + +#define MICROPY_ALLOC_PATH_MAX (256) +#define MICROPY_ALLOC_PARSE_CHUNK_INIT (16) + +#define MICROPY_ERROR_REPORTING MICROPY_ERROR_REPORTING_NORMAL +#define MICROPY_USE_INTERNAL_ERRNO (1) +#define MICROPY_ENABLE_SCHEDULER (1) +#define MICROPY_SCHEDULER_STATIC_NODES (0) +#define MICROPY_SCHEDULER_DEPTH (64)// 8 +#define MICROPY_REPL_AUTO_INDENT (1) +#define MICROPY_PY_UTIME_MP_HAL (1) +#define MICROPY_PY_THREAD (1) +#define MICROPY_READER_VFS (1) +#define MICROPY_KBD_EXCEPTION (1) +#define MICROPY_PY_SOFT_RESET (0) +#define MICROPY_PERSISTENT_CODE_LOAD (1) #ifndef SSIZE_MAX #define SSIZE_MAX 0xFFFFFFFF #endif -#if defined(PLAT_Unisoc) \ - || defined(PLAT_Unisoc_8850) \ - || defined(PLAT_ASR_1803s) \ - || defined(PLAT_RDA) \ - || defined(PLAT_Qualcomm) \ - || defined(PLAT_ASR) -#define MICROPY_PY_REPL_PASSWORD_PROTECT (1) +#if defined(PLAT_Unisoc) +#define MICROPY_PY_REPL_PASSWORD_PROTECT (1) #endif -#if defined(PLAT_SONY_ALT1350) -#define MICROPY_PY_USOCKET_EVENTS (1) -#endif - -#if defined(PLAT_SONY_ALT1350) -#define MICROPY_PY_USSL (1) -#define MICROPY_SSL_MBEDTLS (1) -#endif - -#if defined(PLAT_Qualcomm) -#define mp_type_fileio mp_type_vfs_efs_fileio -#define mp_type_textio mp_type_vfs_efs_textio -#elif defined(PLAT_EIGEN) -#define mp_type_fileio mp_type_vfs_lfs2_fileio -#define mp_type_textio mp_type_vfs_lfs2_textio -#elif defined(PLAT_EIGEN_718) -#define mp_type_fileio mp_type_vfs_lfs2_fileio -#define mp_type_textio mp_type_vfs_lfs2_textio -#else -#define mp_type_fileio mp_type_vfs_lfs1_fileio -#define mp_type_textio mp_type_vfs_lfs1_textio -#endif - - // type definitions for the specific machine typedef intptr_t mp_int_t; // must be pointer size @@ -166,40 +109,18 @@ typedef long mp_off_t; #define UINT_FMT "%lu" #define INT_FMT "%ld" - #if MICROPY_ENABLE_GC #ifndef MICROPY_QPY_GC_HEAP_SIZE -#define MICROPY_QPY_GC_HEAP_SIZE (512 * 1024) +#define MICROPY_QPY_GC_HEAP_SIZE (512 * 1024) #endif -#define MICROPY_GC_HEAP_SIZE (MICROPY_QPY_GC_HEAP_SIZE) +#define MICROPY_GC_HEAP_SIZE (MICROPY_QPY_GC_HEAP_SIZE) #endif #ifdef MICROPY_QPY_MAIN_TASK_STACK_SIZE -#define MP_QPY_TASK_STACK_SIZE (MICROPY_QPY_MAIN_TASK_STACK_SIZE) -#else -#if defined(PLAT_RDA) -#define MP_QPY_TASK_STACK_SIZE (32 * 1024) -#elif defined(PLAT_EIGEN) -#define MP_QPY_TASK_STACK_SIZE (32 * 1024) -#elif defined(PLAT_EIGEN_718) -#define MP_QPY_TASK_STACK_SIZE (8 * 1024) -#elif defined(PLAT_ECR6600) -#define MP_QPY_TASK_STACK_SIZE (8 * 1024) -#elif defined(PLAT_aic8800m40) -#define MP_QPY_TASK_STACK_SIZE (10 * 1024) -#elif defined(PLAT_Unisoc_8850) || defined(PLAT_Unisoc_8850_R02) - #if defined(BOARD_EC600GCN_LD) || defined(BOARD_EC800GCN_LD) || defined(BOARD_EC800GCN_LD_XBND) \ - || defined(BOARD_EC800GCN_LD_HRXM) || defined(BOARD_EC600GCN_LD_YM) || defined(BOARD_EC800GCN_TT) \ - || defined(BOARD_EG800GLA_LD) - #define MP_QPY_TASK_STACK_SIZE (16 * 1024) - #else - #define MP_QPY_TASK_STACK_SIZE (64 * 1024) - #endif +#define MP_QPY_TASK_STACK_SIZE (MICROPY_QPY_MAIN_TASK_STACK_SIZE) #else -#define MP_QPY_TASK_STACK_SIZE (64 * 1024) +#define MP_QPY_TASK_STACK_SIZE (64 * 1024) #endif -#endif - // We need to provide a declaration/definition of alloca() #include @@ -223,7 +144,6 @@ typedef long mp_off_t; #define MP_STATE_PORT MP_STATE_VM - #if MICROPY_PY_THREAD #define MICROPY_EVENT_POLL_HOOK \ do { \ @@ -235,7 +155,7 @@ typedef long mp_off_t; #else #define MICROPY_EVENT_POLL_HOOK \ do { \ - extern void mp_handle_pending(bool); \ + extern void mp_handle_pending(mp_handle_pending_behaviour_t behavior); \ mp_handle_pending(true); \ asm ("waiti 0"); \ } while (0); diff --git a/ports/quectel/mpconfigport.mk b/ports/quectel/mpconfigport.mk deleted file mode 100644 index a6aebebfcffc6..0000000000000 --- a/ports/quectel/mpconfigport.mk +++ /dev/null @@ -1,21 +0,0 @@ -# Enable/disable modules and 3rd-party libs to be included in interpreter - -ifeq ($(strip $(PLAT)), $(filter $(PLAT),Unisoc Unisoc_8910_R05 Unisoc_8910_R06)) - -MICROPY_VFS_LFS1=1 -MICROPY_VFS_LFS2=0 - -ifeq ($(MICROPY_VFS_LFS_VERSION), 1) -MICROPY_VFS_LFS1=1 -MICROPY_VFS_LFS2=0 -else -MICROPY_VFS_LFS1=0 -MICROPY_VFS_LFS2=1 -endif - -else - -MICROPY_VFS_LFS1=0 -MICROPY_VFS_LFS2=1 - -endif diff --git a/ports/quectel/quectel.mk b/ports/quectel/quectel.mk index dd11e06fed431..21fc88a4fb75c 100644 --- a/ports/quectel/quectel.mk +++ b/ports/quectel/quectel.mk @@ -1,4 +1,3 @@ - PLAT_DFLAGS = $(addprefix -D,$(DFLAGS)) PLAT_CFLAGS = $(QUEC_CFLAGS) PLAT_CFLAGS += -Wno-unused-parameter -Wformat=0 -Wno-unused-function @@ -33,19 +32,6 @@ INC += -I$(ROOT)/system/at INC += -I$(ROOT)/system/aliiot ifeq ($(strip $(PLAT)),Unisoc) -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT)) -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/apps -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/priv -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/lwip/prot -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/netif -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix/arpa -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix/net -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix/netinet -INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/src/include/posix/sys INC += -I$(ROOT)/system/at INC += -I$(ROOT)/system/esim endif From 25ee3d07fad292bec646f3bcd4eb1d9898b7816e Mon Sep 17 00:00:00 2001 From: Nikola Neskovic Date: Fri, 3 Apr 2026 09:32:45 +0200 Subject: [PATCH 11/13] quectel: Remove platform dependant code. --- ports/quectel/gccollect.c | 35 +---------------------------------- ports/quectel/main.c | 34 ++-------------------------------- ports/quectel/mpthreadport.h | 8 +------- 3 files changed, 4 insertions(+), 73 deletions(-) diff --git a/ports/quectel/gccollect.c b/ports/quectel/gccollect.c index 344f507074f1a..6fee0046a0ff1 100644 --- a/ports/quectel/gccollect.c +++ b/ports/quectel/gccollect.c @@ -32,21 +32,6 @@ #include "mpthread.h" #include "gccollect.h" -#if defined(PLAT_RDA) -unsigned int ReadSP(void) { - uint32_t res; - __asm volatile ( - "move %0, $29\n" - : "=r" (res) - : - : - ); - - return res; -} -#elif defined(PLAT_ECR6600) - -#else unsigned int ReadSP(void) { uint32_t res; __asm volatile ( @@ -58,7 +43,6 @@ unsigned int ReadSP(void) { return res; } -#endif void gc_stacktop_set(void *ptr) { MP_STATE_PORT(global_stacktop_ptr) = ptr; @@ -69,17 +53,11 @@ void gc_collect(void) { #if 0 uint32_t start = mp_hal_ticks_us(); #endif - #if defined(PLAT_ECR6600) - int val = 0; - #endif // start the GC gc_collect_start(); - #if defined(PLAT_ECR6600) - uintptr_t sp = (uintptr_t)&val; - #else // get the registers and the sp uintptr_t sp = (uintptr_t)ReadSP(); - #endif + if (mp_is_python_thread()) { // trace the stack, including the registers (since they live on the stack in this function) gc_collect_root((void **)sp, ((uint32_t)MP_STATE_THREAD(stack_top) - sp) / sizeof(uint32_t)); @@ -96,17 +74,6 @@ void gc_collect(void) { // end the GC gc_collect_end(); - - #if 0 - // print GC info - uint32_t ticks = mp_hal_ticks_us() - start; - gc_info_t info; - gc_info(&info); - printf("GC@%lu %lums\n", start, ticks); - printf(" " UINT_FMT " total\n", info.total); - printf(" " UINT_FMT " : " UINT_FMT "\n", info.used, info.free); - printf(" 1=" UINT_FMT " 2=" UINT_FMT " m=" UINT_FMT "\n", info.num_1block, info.num_2block, info.max_block); - #endif } MP_REGISTER_ROOT_POINTER(volatile void *global_stacktop_ptr); diff --git a/ports/quectel/main.c b/ports/quectel/main.c index 8d85193288116..7d781aa1514da 100644 --- a/ports/quectel/main.c +++ b/ports/quectel/main.c @@ -61,8 +61,7 @@ Helios_Thread_t ql_micropython_task_ref; #define MP_TASK_STACK_SIZE (MP_QPY_TASK_STACK_SIZE) #define MP_TASK_STACK_LEN (MP_TASK_STACK_SIZE / sizeof(uint32_t)) -#if (defined(PLAT_ASR) || defined(PLAT_Unisoc) || defined(PLAT_ASR_1803s) || defined(PLAT_ASR_1803sc) || defined(PLAT_Qualcomm) \ - || defined(PLAT_ASR_1606) || defined(PLAT_ASR_1609) || defined(PLAT_Unisoc_8910_R05) || defined(PLAT_Unisoc_8910_R06) || defined(PLAT_ASR_1602)) // support +#if (defined(PLAT_Unisoc)) #define QPY_ASSERT_SUPPORT 1 #endif @@ -85,7 +84,6 @@ void NORETURN __fatal_error(const char *msg) { } #ifndef NDEBUG -#if !defined(PLAT_Qualcomm) void MP_WEAK __assert_func(const char *file, int line, const char *func, const char *expr) { #if QPY_ASSERT_SUPPORT Helios_Assert(expr, file, line, ""); @@ -108,18 +106,10 @@ void __assert_fail(const char *__message, } #endif -#endif - static char *stack_top; #if MICROPY_ENABLE_GC -#if defined(PLAT_ECR6600) -static char __attribute__((__section__(".data"))) heap[MICROPY_GC_HEAP_SIZE]; -#elif defined(PLAT_SONY_ALT1350) -static char __attribute__((__section__("gpm1_working_data"))) heap[MICROPY_GC_HEAP_SIZE]; -#else static char heap[MICROPY_GC_HEAP_SIZE]; #endif -#endif extern pyexec_mode_kind_t pyexec_mode_kind; @@ -168,11 +158,7 @@ void quecpython_task(void *arg) { soft_reset: mp_stack_set_top((void *)&stack_dummy); - #if defined(PLAT_ECR6600) || defined(PLAT_aic8800m40) // unit: Byte - mp_stack_set_limit(MP_TASK_STACK_SIZE * sizeof(uint32_t) - 1024); - #else mp_stack_set_limit(MP_TASK_STACK_SIZE - 1024); - #endif stack_top = (char *)&stack_dummy; #if MICROPY_ENABLE_GC gc_init(heap, heap + sizeof(heap)); @@ -184,21 +170,7 @@ void quecpython_task(void *arg) { readline_init0(); // run boot-up scripts - #if defined(PLAT_RDA) - pyexec_frozen_module("_boot_RDA.py"); - #elif defined(PLAT_Qualcomm) - pyexec_frozen_module("_boot_Qualcomm.py"); - #elif defined(BOARD_EC800ECN_LC_WDF) - pyexec_frozen_module("_boot_WDF.py");// EIGEN WDF CUNSTOMER BOOT WITH SINGLE FILE SYSTEM - #elif defined(PLAT_ECR6600) || defined(PLAT_aic8800m40) - pyexec_frozen_module("_boot_WIFI.py"); - #elif defined(BOARD_EC600GCN_LA_CDD) - pyexec_frozen_module("_boot_dsds.py"); - #elif defined(PLAT_SONY_ALT1350) - pyexec_frozen_module("_boot_SONY.py", false); - #else pyexec_frozen_module("_boot.py", false); - #endif if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL #if MICROPY_PY_KBD_EXCEPTION @@ -213,7 +185,7 @@ void quecpython_task(void *arg) { MAINPY_RUNNING_FLAG_SET(); #endif - int ret = pyexec_file_if_exists("/usr/main.py"); + int ret = pyexec_file_if_exists("/main.py"); if (ret & PYEXEC_FORCED_EXIT) { goto soft_reset_exit; } @@ -285,9 +257,7 @@ void quecpython_task(void *arg) { qpy_callback_para_link_free_all(); #endif mp_deinit(); - #if !defined(PLAT_RDA) fflush(stdout); - #endif goto soft_reset; } diff --git a/ports/quectel/mpthreadport.h b/ports/quectel/mpthreadport.h index 84e7347d3814b..4ee4bf063e92a 100644 --- a/ports/quectel/mpthreadport.h +++ b/ports/quectel/mpthreadport.h @@ -29,15 +29,9 @@ #include "helios_os.h" -#if defined(PLAT_EIGEN) || defined(PLAT_EIGEN_718) -#define MP_THREAD_MIN_STACK_SIZE (4 * 1024) -#define MP_THREAD_DEFAULT_STACK_SIZE (MP_THREAD_MIN_STACK_SIZE + 1024 + 1024) -#define MP_THREAD_PRIORITY 100 -#else #define MP_THREAD_MIN_STACK_SIZE (32 * 1024) #define MP_THREAD_DEFAULT_STACK_SIZE (MP_THREAD_MIN_STACK_SIZE + 1024) #define MP_THREAD_PRIORITY 100 -#endif typedef Helios_Mutex_t mp_thread_mutex_t; @@ -67,4 +61,4 @@ void mp_thread_semphore_del(mp_thread_semphore_t *sem); void mp_new_thread_add(uint32_t th_id, uint32_t stack_size); -#endif // MICROPY_INCLUDED_MPTHREADPORT_H +#endif // MICROPY_INCLUDED_MPTHREADPORT_H \ No newline at end of file From 968d38f792c4a7014b46920804b8253e98ff51aa Mon Sep 17 00:00:00 2001 From: Nikola Neskovic Date: Fri, 3 Apr 2026 09:57:03 +0200 Subject: [PATCH 12/13] quectel: Add random number generator. --- ports/quectel/mphalport.c | 24 ++++++++++++++++++++++++ ports/quectel/mphalport.h | 6 +++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/ports/quectel/mphalport.c b/ports/quectel/mphalport.c index 3e40740e69960..7de68064d129f 100644 --- a/ports/quectel/mphalport.c +++ b/ports/quectel/mphalport.c @@ -51,6 +51,10 @@ static int mthread_sleep_flag = 0; #define IS_MTHREAD_IN_SLEEP() (1 == mthread_sleep_flag) #define MP_HAL_PORT_CHECK_OPEN (mp_hal_cdcPort_State == 1) +#if !defined(MICROPY_PY_RANDOM_SEED_INIT_FUNC) +#define MICROPY_PY_RANDOM_SEED_INIT_FUNC Helios_RTC_GetSecond() +#endif + static uint8_t stdin_ringbuf_array[256]; ringbuf_t stdin_ringbuf = {stdin_ringbuf_array, sizeof(stdin_ringbuf_array), 0, 0}; @@ -209,6 +213,26 @@ uint64_t mp_hal_time_ns(void) { return 0; } +static void mp_hal_random_init(void) { + static bool seeded = false; + if (!seeded) { + seeded = true; + srand(MICROPY_PY_RANDOM_SEED_INIT_FUNC); + } +} + +void mp_hal_get_random(size_t n, uint8_t *buf) { + mp_hal_random_init(); + uint32_t r = 0; + for (size_t i = 0; i < n; i++) { + if ((i & 3) == 0) { + r = rand(); // returns 32-bit random number + } + buf[i] = r; + r >>= 8; + } +} + void mp_hal_delay_ms(mp_uint_t ms) { mp_uint_t dt = 0; mp_uint_t t0 = 0, t1 = 0; diff --git a/ports/quectel/mphalport.h b/ports/quectel/mphalport.h index 1c1e1b5eee800..534f3a93f8b2a 100644 --- a/ports/quectel/mphalport.h +++ b/ports/quectel/mphalport.h @@ -62,4 +62,8 @@ void mp_hal_port_open(uint8_t state); void mp_hal_set_interrupt_char(int c); uint64_t mp_hal_time_ns(void); -#endif + +static void mp_hal_random_init(void); +void mp_hal_get_random(size_t n, uint8_t *buf); + +#endif \ No newline at end of file From 643552a9281ba494d40a6a8bc03a5492048c6965 Mon Sep 17 00:00:00 2001 From: Nikola Neskovic Date: Fri, 3 Apr 2026 10:22:21 +0200 Subject: [PATCH 13/13] quectel: Add time module. --- ports/quectel/main.c | 4 +++ ports/quectel/modtime.c | 59 ++++++++++++++++++++++++++++++++++++ ports/quectel/mpconfigport.h | 6 +++- ports/quectel/mphalport.c | 4 --- ports/quectel/mphalport.h | 2 -- 5 files changed, 68 insertions(+), 7 deletions(-) create mode 100644 ports/quectel/modtime.c diff --git a/ports/quectel/main.c b/ports/quectel/main.c index 7d781aa1514da..70b46f30df852 100644 --- a/ports/quectel/main.c +++ b/ports/quectel/main.c @@ -44,6 +44,7 @@ #include #include "helios.h" #include "helios_os.h" +#include "helios_rtc.h" #include "helios_debug.h" #include "mphalport.h" #if MICROPY_KBD_EXCEPTION @@ -65,6 +66,8 @@ Helios_Thread_t ql_micropython_task_ref; #define QPY_ASSERT_SUPPORT 1 #endif +extern uint64_t mp_time_start_second; + void nlr_jump_fail(void *val) { #if QPY_ASSERT_SUPPORT Helios_Assert(__func__, __FILE__, __LINE__, ""); @@ -171,6 +174,7 @@ void quecpython_task(void *arg) { // run boot-up scripts pyexec_frozen_module("_boot.py", false); + mp_time_start_second = Helios_RTC_GetSecond(); if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL #if MICROPY_PY_KBD_EXCEPTION diff --git a/ports/quectel/modtime.c b/ports/quectel/modtime.c new file mode 100644 index 0000000000000..e008822e97d1d --- /dev/null +++ b/ports/quectel/modtime.c @@ -0,0 +1,59 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 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 "helios_debug.h" +#include "helios_rtc.h" + +uint64_t mp_time_start_second; + +static void mp_time_localtime_get(timeutils_struct_time_t *tm) { + Helios_RTCTime rtc_tm; + Helios_RTC_GetLocalTime(&rtc_tm); + tm->tm_year = rtc_tm.tm_year; + tm->tm_mon = rtc_tm.tm_mon; + tm->tm_mday = rtc_tm.tm_mday; + tm->tm_hour = rtc_tm.tm_hour; + tm->tm_min = rtc_tm.tm_min; + tm->tm_sec = rtc_tm.tm_sec; + tm->tm_wday = rtc_tm.tm_wday; + tm->tm_yday = 0; +} + +// return rtc seconds since power on +static mp_obj_t mp_time_time_get(void) { + uint64_t seconds = Helios_RTC_GetSecond() - mp_time_start_second; + return mp_obj_new_int_from_ull(seconds); +} + +uint64_t mp_hal_time_ns(void) { + return (Helios_RTC_GetSecond() - mp_time_start_second) * 1000000000ULL; +} diff --git a/ports/quectel/mpconfigport.h b/ports/quectel/mpconfigport.h index 451e310381e49..937151f88bd8e 100644 --- a/ports/quectel/mpconfigport.h +++ b/ports/quectel/mpconfigport.h @@ -46,7 +46,7 @@ #define MICROPY_VFS (1) #define MICROPY_PY_VFS (0) #define MICROPY_VFS_LFS2 (1) -#define MICROPY_PY_TIME (0) +#define MICROPY_PY_TIME (1) #define MICROPY_PY_HEAPQ (0) #define MICROPY_PY_OS (1) #define MICROPY_PY_PLATFORM (0) @@ -58,6 +58,10 @@ #define MICROPY_PY_DEFLATE (0) #define MICROPY_OPT_COMPUTED_GOTO (1) +#define MICROPY_PY_TIME_TIME_TIME_NS (1) +#define MICROPY_PY_TIME_GMTIME_LOCALTIME_MKTIME (1) +#define MICROPY_PY_TIME_INCLUDEFILE "ports/quectel/modtime.c" + /******************************** base define **********************************/ // options to control how MicroPython is built #define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES) diff --git a/ports/quectel/mphalport.c b/ports/quectel/mphalport.c index 7de68064d129f..629f51a0dc2f1 100644 --- a/ports/quectel/mphalport.c +++ b/ports/quectel/mphalport.c @@ -209,10 +209,6 @@ mp_uint_t mp_hal_ticks_us(void) { return (mp_uint_t)Helios_RTC_TicksToUs(); } -uint64_t mp_hal_time_ns(void) { - return 0; -} - static void mp_hal_random_init(void) { static bool seeded = false; if (!seeded) { diff --git a/ports/quectel/mphalport.h b/ports/quectel/mphalport.h index 534f3a93f8b2a..065ac968440f2 100644 --- a/ports/quectel/mphalport.h +++ b/ports/quectel/mphalport.h @@ -61,8 +61,6 @@ void mp_hal_port_open(uint8_t state); void mp_hal_set_interrupt_char(int c); -uint64_t mp_hal_time_ns(void); - static void mp_hal_random_init(void); void mp_hal_get_random(size_t n, uint8_t *buf);