diff --git a/.vs/RTLGDB/v14/.suo b/.vs/RTLGDB/v14/.suo
new file mode 100644
index 0000000..645b17a
Binary files /dev/null and b/.vs/RTLGDB/v14/.suo differ
diff --git a/.vs/config/applicationhost.config b/.vs/config/applicationhost.config
new file mode 100644
index 0000000..b42cd34
--- /dev/null
+++ b/.vs/config/applicationhost.config
@@ -0,0 +1,1030 @@
+п»ї
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/External Tools/ExternalToolsRTL-2017-11-19.vssettings b/External Tools/ExternalToolsRTL-2017-11-19.vssettings
new file mode 100644
index 0000000..1505c96
--- /dev/null
+++ b/External Tools/ExternalToolsRTL-2017-11-19.vssettings
@@ -0,0 +1 @@
+-s runramtruemingw32-make.exe0$(ProjectDir)false0{00000000-0000-0000-0000-000000000000}falsetrue[RTL] Run in RAMfalsetruefalse-s runsdramtruemingw32-make.exe1$(ProjectDir)false0{00000000-0000-0000-0000-000000000000}falsetrue[RTL] Run in SDRAMfalsetruefalse-s flashburntruemingw32-make.exe2$(ProjectDir)false0{00000000-0000-0000-0000-000000000000}falsetrue[RTL] Flash and Runfalsetruefalse-s flashboottruemingw32-make.exe3$(ProjectDir)false0{00000000-0000-0000-0000-000000000000}falsetrue[RTL] Flash Bootfalsetruefalse-s flashwebfstruemingw32-make.exe4$(ProjectDir)false0{00000000-0000-0000-0000-000000000000}falsetrue[RTL] Flash WEB Imagefalsetruefalse-s resettruemingw32-make.exe5$(ProjectDir)false0{00000000-0000-0000-0000-000000000000}falsetrue[RTL] Reset CPUfalsetruefalse-select USB -device Cortex-M3 -if SWD -speed 1000 -irfalseJLinkGDBServer.exe6$(ProjectDir)true0{00000000-0000-0000-0000-000000000000}falsetrue[RTL] Start J-Link GDB Server M3falsefalsefalse-select USB -device Cortex-M4 -if SWD -speed 1000 -irfalseJLinkGDBServer.exe7$(ProjectDir)true0{00000000-0000-0000-0000-000000000000}falsetrue[RTL] Start J-Link GDB Server M4falsefalsefalse
\ No newline at end of file
diff --git a/README.md b/README.md
index 8377f3b..be1326d 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,10 @@
-# RTL00_WEB_VS
+п»ї# RTL00_WEB_VS
+
+Описание порта для Visual Studio 2015:
+https://adelectronics.ru/2017/10/18/rtl8195am-rtl871xax-%d0%bd%d0%b0%d0%bf%d0%b8%d1%81%d0%b0%d0%bd%d0%b8%d0%b5-%d0%bf%d1%80%d0%be%d1%88%d0%b8%d0%b2%d0%ba%d0%b8-%d0%b8-%d0%be%d1%82%d0%bb%d0%b0%d0%b4%d0%ba%d0%b0-%d0%b2-visual-studio-20/
+
+Оригинальный проект:
+https://github.com/pvvx/RTL00_WEB
+
+Пример аппаратной части на основе RTL8711AM:
+https://adelectronics.ru/2017/09/29/rtl8711am-%d1%81%d1%85%d0%b5%d0%bc%d0%be%d1%82%d0%b5%d1%85%d0%bd%d0%b8%d0%ba%d0%b0-%d0%bf%d0%be%d1%80%d1%82%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b3%d0%be-%d1%83%d1%81%d1%82%d1%80%d0%be%d0%b9%d1%81/
\ No newline at end of file
diff --git a/RTLGDB.VC.db b/RTLGDB.VC.db
new file mode 100644
index 0000000..b3d6f1f
Binary files /dev/null and b/RTLGDB.VC.db differ
diff --git a/RTLGDB.sln b/RTLGDB.sln
new file mode 100644
index 0000000..979f96c
--- /dev/null
+++ b/RTLGDB.sln
@@ -0,0 +1,28 @@
+п»ї
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25420.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RTLGDB", "RTLGDB\RTLGDB.vcxproj", "{3D8B16B6-9763-48AD-A514-F45680E8613B}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {3D8B16B6-9763-48AD-A514-F45680E8613B}.Debug|x64.ActiveCfg = Debug|x64
+ {3D8B16B6-9763-48AD-A514-F45680E8613B}.Debug|x64.Build.0 = Debug|x64
+ {3D8B16B6-9763-48AD-A514-F45680E8613B}.Debug|x86.ActiveCfg = Debug|Win32
+ {3D8B16B6-9763-48AD-A514-F45680E8613B}.Debug|x86.Build.0 = Debug|Win32
+ {3D8B16B6-9763-48AD-A514-F45680E8613B}.Release|x64.ActiveCfg = Release|x64
+ {3D8B16B6-9763-48AD-A514-F45680E8613B}.Release|x64.Build.0 = Release|x64
+ {3D8B16B6-9763-48AD-A514-F45680E8613B}.Release|x86.ActiveCfg = Release|Win32
+ {3D8B16B6-9763-48AD-A514-F45680E8613B}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/RTLGDB/Assets/LinuxDebugger.xaml b/RTLGDB/Assets/LinuxDebugger.xaml
new file mode 100644
index 0000000..62f89b1
--- /dev/null
+++ b/RTLGDB/Assets/LinuxDebugger.xaml
@@ -0,0 +1,82 @@
+п»ї
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/RTLGDB/Assets/LocalDebugger.xaml b/RTLGDB/Assets/LocalDebugger.xaml
new file mode 100644
index 0000000..8b12d3c
--- /dev/null
+++ b/RTLGDB/Assets/LocalDebugger.xaml
@@ -0,0 +1,63 @@
+п»ї
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/RTLGDB/Assets/OCDDebugger.xaml b/RTLGDB/Assets/OCDDebugger.xaml
new file mode 100644
index 0000000..d36f931
--- /dev/null
+++ b/RTLGDB/Assets/OCDDebugger.xaml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/RTLGDB/Assets/linux_nmake.xaml b/RTLGDB/Assets/linux_nmake.xaml
new file mode 100644
index 0000000..b429ebd
--- /dev/null
+++ b/RTLGDB/Assets/linux_nmake.xaml
@@ -0,0 +1,69 @@
+п»ї
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/RTLGDB/Project/FreeRTOSConfig.h b/RTLGDB/Project/FreeRTOSConfig.h
new file mode 100644
index 0000000..d5d86d9
--- /dev/null
+++ b/RTLGDB/Project/FreeRTOSConfig.h
@@ -0,0 +1,212 @@
+/*
+ FreeRTOS V7.3.0 - Copyright (C) 2012 Real Time Engineers Ltd.
+
+ FEATURES AND PORTS ARE ADDED TO FREERTOS ALL THE TIME. PLEASE VISIT
+ http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ ***************************************************************************
+ * *
+ * FreeRTOS tutorial books are available in pdf and paperback. *
+ * Complete, revised, and edited pdf reference manuals are also *
+ * available. *
+ * *
+ * Purchasing FreeRTOS documentation will not only help you, by *
+ * ensuring you get running as quickly as possible and with an *
+ * in-depth knowledge of how to use FreeRTOS, it will also help *
+ * the FreeRTOS project to continue with its mission of providing *
+ * professional grade, cross platform, de facto standard solutions *
+ * for microcontrollers - completely free of charge! *
+ * *
+ * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
+ * *
+ * Thank you for using FreeRTOS, and thank you for your support! *
+ * *
+ ***************************************************************************
+
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+ >>>NOTE<<< The modification to the GPL is included to allow you to
+ distribute a combined work that includes FreeRTOS without being obliged to
+ provide the source code for proprietary components outside of the FreeRTOS
+ kernel. FreeRTOS is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details. You should have received a copy of the GNU General Public
+ License and the FreeRTOS license exception along with FreeRTOS; if not it
+ can be viewed here: http://www.freertos.org/a00114.html and also obtained
+ by writing to Richard Barry, contact details for whom are available on the
+ FreeRTOS WEB site.
+
+ 1 tab == 4 spaces!
+
+ ***************************************************************************
+ * *
+ * Having a problem? Start by reading the FAQ "My application does *
+ * not run, what could be wrong?" *
+ * *
+ * http://www.FreeRTOS.org/FAQHelp.html *
+ * *
+ ***************************************************************************
+
+
+ http://www.FreeRTOS.org - Documentation, training, latest versions, license
+ and contact details.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool.
+
+ Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell
+ the code with commercial support, indemnification, and middleware, under
+ the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also
+ provide a safety engineered and independently SIL3 certified version under
+ the SafeRTOS brand: http://www.SafeRTOS.com.
+*/
+
+#ifndef FREERTOS_CONFIG_H
+#define FREERTOS_CONFIG_H
+#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
+#include
+extern uint32_t SystemCoreClock;
+#endif
+
+/*-----------------------------------------------------------
+ * Application specific definitions.
+ *
+ * These definitions should be adjusted for your particular hardware and
+ * application requirements.
+ *
+ * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
+ * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
+ *
+ * See http://www.freertos.org/a00110.html.
+ *----------------------------------------------------------*/
+
+#define configUSE_STACK_TCM_HEAP 5 // RTL871xAx/RTL8195Ax Stack priority used TCM HEAP
+#define configUSE_PREEMPTION 1
+#define configUSE_IDLE_HOOK 1
+#define configUSE_TICK_HOOK 0
+#define configCPU_CLOCK_HZ ( SystemCoreClock )
+#define configTICK_RATE_HZ ( ( uint32_t ) 1000 )
+#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 70 )
+#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 90 * 1024 ) ) // use HEAP5
+#define configMAX_TASK_NAME_LEN ( 10 )
+#define configUSE_TRACE_FACILITY 0
+#define configUSE_16_BIT_TICKS 0
+#define configIDLE_SHOULD_YIELD 0
+#define configUSE_CO_ROUTINES 1
+#define configUSE_MUTEXES 1
+#define configUSE_TIMERS 1
+
+#define configMAX_PRIORITIES ( 11 )
+#define PRIORITIE_OFFSET ( 4 )
+
+#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
+
+#define configUSE_COUNTING_SEMAPHORES 1
+#define configUSE_ALTERNATIVE_API 0
+#define configCHECK_FOR_STACK_OVERFLOW 0
+#define configUSE_RECURSIVE_MUTEXES 1
+#define configQUEUE_REGISTRY_SIZE 0
+#define configGENERATE_RUN_TIME_STATS 1
+
+#if configGENERATE_RUN_TIME_STATS
+#define configUSE_STATS_FORMATTING_FUNCTIONS 1
+#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() //( ulHighFrequencyTimerTicks = 0UL )
+#define portGET_RUN_TIME_COUNTER_VALUE() xTickCount //ulHighFrequencyTimerTicks
+#undef configUSE_TRACE_FACILITY
+#define configUSE_TRACE_FACILITY 1
+#define portCONFIGURE_STATS_PEROID_VALUE 1000 //unit Ticks
+#endif
+
+#define configTIMER_TASK_PRIORITY ( 1 )
+
+#ifdef CONFIG_UVC
+#define configTIMER_QUEUE_LENGTH ( 20 )
+#else
+#define configTIMER_QUEUE_LENGTH ( 10 )
+#endif
+
+#define configTIMER_TASK_STACK_DEPTH ( 512 ) //USE_MIN_STACK_SIZE modify from 512 to 256
+
+#if (__IASMARM__ != 1)
+
+extern void freertos_pre_sleep_processing(uint32_t *expected_idle_time);
+extern void freertos_post_sleep_processing(uint32_t *expected_idle_time);
+extern int freertos_ready_to_sleep();
+
+/* Enable tickless power saving. */
+#define configUSE_TICKLESS_IDLE 1
+
+/* In wlan usage, this value is suggested to use value less than 80 milliseconds */
+#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2
+
+/* It's magic trick that let us can use our own sleep function */
+#define configPRE_SLEEP_PROCESSING( x ) ( freertos_pre_sleep_processing(&x) )
+
+#define configPOST_SLEEP_PROCESSING( x ) ( freertos_post_sleep_processing(&x) )
+
+/* It's magic trick that let us can enable/disable tickless dynamically */
+#define traceLOW_POWER_IDLE_BEGIN(); do { \
+ if (!freertos_ready_to_sleep()) { \
+ mtCOVERAGE_TEST_MARKER(); \
+ break; \
+ }
+
+ // portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );
+
+#define traceLOW_POWER_IDLE_END(); } while (0);
+
+/* It's FreeRTOS related feature but it's not included in FreeRTOS design. */
+#define configUSE_WAKELOCK_PMU 1
+
+#endif // #if (__IASMARM__ != 1)
+
+/* Set the following definitions to 1 to include the API function, or zero
+to exclude the API function. */
+#define INCLUDE_vTaskPrioritySet 1
+#define INCLUDE_uxTaskPriorityGet 1
+#define INCLUDE_vTaskDelete 1
+#define INCLUDE_vTaskCleanUpResources 0
+#define INCLUDE_vTaskSuspend 1
+#define INCLUDE_vTaskDelayUntil 1
+#define INCLUDE_vTaskDelay 1
+#define INCLUDE_pcTaskGetTaskName 1
+#define INCLUDE_xTimerPendFunctionCall 1
+
+/* Cortex-M specific definitions. */
+#ifdef __NVIC_PRIO_BITS
+ /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
+ #define configPRIO_BITS __NVIC_PRIO_BITS
+#else
+ #define configPRIO_BITS 4 /* 15 priority levels */
+#endif
+
+
+/* The lowest interrupt priority that can be used in a call to a "set priority"
+function. */
+#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x0f
+
+/* The highest interrupt priority that can be used by any interrupt service
+routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
+INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
+PRIORITY THAN THIS! (higher priorities are lower numeric values. */
+#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
+
+
+/* Interrupt priorities used by the kernel port layer itself. These are generic
+to all Cortex-M ports, and do not rely on any particular library functions. */
+#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
+/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
+See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
+#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
+
+//#define RTK_MODE_TIMER
+
+
+#define INCLUDE_uxTaskGetStackHighWaterMark 1
+
+#endif /* FREERTOS_CONFIG_H */
diff --git a/RTLGDB/Project/MLX90614/MLX90614.c b/RTLGDB/Project/MLX90614/MLX90614.c
new file mode 100644
index 0000000..2a40e88
--- /dev/null
+++ b/RTLGDB/Project/MLX90614/MLX90614.c
@@ -0,0 +1,413 @@
+/*
+ * MLX90614drv.c
+ * https://esp8266.ru/forum/threads/i2c-na-rtl.2450/
+ * Created on: 02/09/2017
+ * Author: pvvx
+ */
+#include
+#include "rtl8195a.h"
+#include "device.h"
+#include "PinNames.h"
+
+#include "basic_types.h"
+#include "diag.h"
+#include "osdep_api.h"
+#include "timer_api.h"
+
+//#include "i2c_api.h"
+//#include "i2c_ex_api.h"
+#include "pinmap.h"
+#include "rtl_lib.h"
+#include "rtl8195a/rtl_libc.h"
+#include "driver/i2c_drv.h"
+#include "platform_stdlib.h"
+#include "web_websocket.h"
+#include "tcpsrv/tcp_srv_conn.h"
+
+#include "hal_com_reg.h"
+
+#define MLX90614_I2CADDR 0x5A
+// RAM
+#define MLX90614_RAWIR1 0x04
+#define MLX90614_RAWIR2 0x05
+#define MLX90614_TA 0x06
+#define MLX90614_TOBJ1 0x07
+#define MLX90614_TOBJ2 0x08
+// EEPROM
+#define MLX90614_TOMAX 0x20
+#define MLX90614_TOMIN 0x21
+#define MLX90614_PWMCTRL 0x22
+#define MLX90614_TARANGE 0x23
+#define MLX90614_EMISS 0x24
+#define MLX90614_CONFIG 0x25
+#define MLX90614_ADDR 0x0E
+#define MLX90614_ID1 0x3C
+#define MLX90614_ID2 0x3D
+#define MLX90614_ID3 0x3E
+#define MLX90614_ID4 0x3F
+#define MLX90614_SLEEP 0xFF
+
+typedef struct _MLX90614_data {
+ union {
+ signed short to1; // Tobj1
+ unsigned char uc[2];
+ } o;
+ union {
+ signed short ta; // Ta
+ unsigned char uc[2];
+ } a;
+} MLX90614DATA, *PMLX90614DATA;
+
+typedef struct _MLX90614drv {
+ unsigned char status;
+ unsigned char addr; // адрес MLX90614 на шине I2C (формат 7 bit)
+ signed char init;
+ unsigned char tmp;
+
+ unsigned short config; // регистр конфигурации MLX90614
+ unsigned short timetik; // время опроса таймером (в us)
+
+ unsigned short count; // счетчик считанных значений
+ unsigned short overrun; // счет переполнений буфера
+
+ unsigned short errs; // счет ошибок на I2C
+ unsigned short buf_idx; // объем буфера pbuf[buf_idx+1], максимальный индекс-номер замера
+ unsigned short buf_rx; // индекс-номер ещё не считанного замера
+ unsigned short buf_tx; // индекс-номер для записи следующего замера
+ PMLX90614DATA pbuf;
+ gtimer_t timer;
+ union { // буфер
+ unsigned char uc[4];
+ unsigned short us[2];
+ signed short ss[2];
+ unsigned int ui;
+ } buf_i2c;
+ i2c_drv_t i2c;
+} MLX90614DRV, *PMLX90614DRV;
+
+
+#define MLX90614_I2C_PIN_SDA PC_4
+#define MLX90614_I2C_PIN_SCL PC_5
+#define MLX90614_I2C_BUS_CLK 50000 // The maximum frequency of the MLX90614 SMBus is 100 KHz and the minimum is 10 KHz.
+#define MLX90614_TIMER TIMER3 // используемый таймер
+
+MLX90614DRV mlx90614drv = {
+ .addr = MLX90614_I2CADDR,
+ .timetik = 10000, // Время опроса таймером: 10000 us
+ .buf_idx = 709, // циклический буфер на 710 замеров (по 4 байт -> sizeof(MLX90614DATA))
+ // Если шаг заполнения 1 ms -> буфер на 0.71 сек
+ // Оптимизация под TCP: (TCP_MSS*2 - 80)/4 = (1460*2 - 80)/4 = 710
+ .i2c.status = DRV_I2C_OFF,
+ .i2c.idx = 1, // I2C1
+ .i2c.io_sel = S0, // PC_4, PC_5
+ .i2c.mode = DRV_I2C_SS_MODE // DRV_I2C_FS_MODE // DRV_I2C_HS_MODE
+};
+
+#define i2c_reg(r) *((volatile uint32 *)(pi2c->base_regs + r))
+
+#define MLX90614_USE_CRC
+
+#ifdef MLX90614_USE_CRC
+unsigned char crc8(unsigned char x) {
+ for (int i = 8; i; i--) {
+ x = ( x << 1 ) ^ ( x & 128 ? 7 : 0 );
+ }
+ return x;
+}
+#endif
+
+
+/* Пример непрерывного чтения регистров Tobj1 и Tobj2
+ * MLX90614 по прерыванию таймера */
+void mlx_tick_handler(void *par) {
+ PMLX90614DRV p = &mlx90614drv;
+ i2c_drv_t *pi2c = &p->i2c;
+ switch(p->status) {
+ default:
+ // Disable controller.
+ i2c_reg(REG_DW_I2C_IC_ENABLE) = 0;
+ p->status = 1;
+ break;
+ case 1:
+ // Master Target Address
+ i2c_reg(REG_DW_I2C_IC_TAR) = p->addr;
+ // Enable controller.
+ i2c_reg(REG_DW_I2C_IC_ENABLE) = BIT_IC_ENABLE;
+ p->status = 2;
+ break;
+ case 3:
+ if (i2c_reg(REG_DW_I2C_IC_RAW_INTR_STAT) & BIT_IC_RAW_INTR_STAT_TX_ABRT) {
+ (volatile uint32)i2c_reg(REG_DW_I2C_IC_CLR_INTR);
+ p->errs++;
+ p->status = 0;
+ break;
+ } else {
+ if(p->pbuf) {
+ PMLX90614DATA pd = p->pbuf + p->buf_tx;
+ // Считаем готовые значения из FIFO ic I2C
+ pd->o.uc[0] = i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+ pd->o.uc[1] = i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+#ifdef MLX90614_USE_CRC
+ // B407B5 -> 0x28 (http://crccalc.com/)
+ if(crc8(pd->o.uc[1] ^ crc8(pd->o.uc[0] ^ 0x28)) != (uint8) i2c_reg(REG_DW_I2C_IC_DATA_CMD)) {
+ i2c_reg(REG_DW_I2C_IC_ENABLE) = 2; // ABORT
+ p->errs++;
+ p->status = 0;
+ break;
+ }
+#endif
+ pd->a.uc[0] = i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+ pd->a.uc[1] = i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+#ifdef MLX90614_USE_CRC
+ // B406B5 -> 0x3D (http://crccalc.com/)
+ if(crc8(pd->a.uc[1] ^ crc8(pd->a.uc[0] ^ 0x3D)) != (uint8) i2c_reg(REG_DW_I2C_IC_DATA_CMD)) {
+ i2c_reg(REG_DW_I2C_IC_ENABLE) = 2; // ABORT
+ p->errs++;
+ p->status = 0;
+ break;
+ }
+#endif
+ if(p->buf_tx >= p->buf_idx) p->buf_tx = 0;
+ else p->buf_tx++;
+ if(p->buf_rx == p->buf_tx) {
+ p->overrun++; // todo: if(p->overrun++ > 100000) deinit() ?
+ if(p->buf_rx >= p->buf_idx) p->buf_rx = 0;
+ else p->buf_rx++;
+ };
+ } else {
+ // удаление из FIFO блока данных
+ (volatile uint32)i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+ (volatile uint32)i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+#ifdef MLX90614_USE_CRC
+ (volatile uint32)i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+#endif
+ (volatile uint32)i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+ (volatile uint32)i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+#ifdef MLX90614_USE_CRC
+ (volatile uint32)i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+#endif
+ };
+ }
+ case 2:
+ // Заполним FIFO ic I2C командами чтения
+ // Write Command.
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = MLX90614_TOBJ1;
+ // Read command & data (3 bytes).
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD | BIT_IC_DATA_CMD_RESTART;
+#ifdef MLX90614_USE_CRC
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD;
+#endif
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD | BIT_IC_DATA_CMD_STOP;
+ // Write Command.
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = MLX90614_TA;
+ // Read command & data (3 bytes).
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD | BIT_IC_DATA_CMD_RESTART;
+#ifdef MLX90614_USE_CRC
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD;
+#endif
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD | BIT_IC_DATA_CMD_STOP;
+ p->status = 3;
+ break;
+ }
+}
+
+uint16 mlx90614_chkdata(uint16 cnt)
+{
+ PMLX90614DRV p = &mlx90614drv;
+ if(p->init <= 0) return 0;
+ int len = p->buf_tx - p->buf_rx;
+ if(len < 0) len += p->buf_idx + 1;
+ if(cnt > (uint16)len) cnt = (uint16)len;
+ return cnt;
+}
+
+size_t mlx90614_getdata(void *pd, uint16 cnt)
+{
+ PMLX90614DRV p = &mlx90614drv;
+ if(p->init <= 0) return 0;
+// cnt = mlx90614_chkdata(cnt);
+ unsigned short *pus = (unsigned short *) pd;
+ taskDISABLE_INTERRUPTS();
+ uint16 buf_rx = p->buf_rx;
+ *pus++ = cnt; // кол-во замеров
+ *pus++ = p->count + p->overrun; // индекс замера для анализа пропусков на стороне приемника
+ // если не пропущено, то равен прошлому + кол-во считанных замеров в прошлом блоке
+ p->count += cnt; // p->overrun = 0;
+ unsigned char *puc = (unsigned char *) pus;
+ if(cnt) {
+ uint16 lend = buf_rx + cnt;
+ if(lend > p->buf_idx) {
+ lend -= p->buf_idx + 1;
+ p->buf_rx = lend;
+ } else {
+ p->buf_rx = lend;
+ lend = 0;
+ };
+ size_t len = (cnt - lend) *sizeof(MLX90614DATA);
+ if(len) memcpy(puc, (void *)(p->pbuf + buf_rx), len);
+ if(lend) memcpy(puc + len, (void *)p->pbuf, lend *sizeof(MLX90614DATA));
+ }
+ taskENABLE_INTERRUPTS();
+ return cnt * sizeof(MLX90614DATA) + 4;
+}
+
+//#define mMIN(a, b) ((ab)?a:b)
+
+#include "web_srv.h"
+#include "websock.h"
+
+int mlx90614_ws(TCP_SERV_CONN *ts_conn, char cmd)
+{
+ PMLX90614DRV p = &mlx90614drv;
+ switch(cmd) {
+ case 'd': // deinit
+ if(p->init > 0) {
+ gtimer_stop(&p->timer);
+ gtimer_deinit(&p->timer);
+ _i2c_deinit(&p->i2c);
+ if(p->pbuf) {
+ free(p->pbuf);
+ p->pbuf = NULL;
+ }
+ p->init = -1;
+ return 0;
+ }
+ return 1;
+ case 'c': // get count
+ return mlx90614_chkdata(p->buf_idx + 1);
+ case 'i': // init
+ return p->init;
+ default: // get_data
+ if(p->init <= 0) {
+ p->status = 0;
+ p->count = 0;
+ p->overrun = 0;
+ p->errs = 0;
+ if(!p->pbuf) {
+ p->pbuf = zalloc((p->buf_idx + 1) * sizeof(MLX90614DATA));
+ if(!p->pbuf) {
+ error_printf("Error create buffer!\n");
+ return -1;
+ };
+ p->buf_tx = 0;
+ p->buf_rx = 0;
+ };
+ _i2c_init(&p->i2c);
+ gtimer_init(&p->timer, MLX90614_TIMER);
+ gtimer_start_periodical(&p->timer, p->timetik, (void*)mlx_tick_handler, (uint32_t)&mlx90614drv);
+ p->init = 1;
+// return 0;
+ }
+ case 'g': // get
+ {
+ uint32 i = mlx90614_chkdata(p->buf_idx + 1);
+ if(i) {
+ WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
+ i = mMIN((web_conn->msgbufsize / sizeof(MLX90614DATA)), i);
+ if(websock_tx_frame(ts_conn, WS_OPCODE_BINARY | WS_FRAGMENT_FIN, web_conn->msgbuf, mlx90614_getdata(web_conn->msgbuf, i)) != ERR_OK)
+ return -1;
+ }
+ return i;
+ }
+ }
+ return -1;
+}
+
+void mlx90614_init(void)
+{
+ PMLX90614DRV p = &mlx90614drv;
+ if(p->init <= 0) {
+ rtl_printf("Init MLX90614\n");
+ p->status = 0;
+ p->count = 0;
+ p->errs = 0;
+ if(!p->pbuf) {
+ p->pbuf = zalloc((p->buf_idx + 1) * sizeof(MLX90614DATA));
+ if(!p->pbuf) {
+ error_printf("Error create buffer!\n");
+ return;
+ };
+ p->buf_tx = 0;
+ p->buf_rx = 0;
+ };
+// (!) Установки драйвера I2C заданы в структуре mlx90614drv
+// _i2c_setup(&p->i2c, MLX90614_I2C_PIN_SDA , MLX90614_I2C_PIN_SCL, DRV_I2C_FS_MODE); // == DRV_I2C_OK?
+ _i2c_init(&p->i2c);
+// _i2c_set_speed(&p->i2c, MLX90614_I2C_BUS_CLK);
+ rtl_printf("I2C%d mode = %d, drvStatus = %d\n", p->i2c.idx, p->i2c.mode, p->i2c.status);
+// (!) Рнициализация MLX90614 перенесена РІ прерывание таймера
+ // Initial a periodical timer
+ gtimer_init(&p->timer, MLX90614_TIMER);
+ // Tick every 0.001 sec (p->timetik)
+ gtimer_start_periodical(&p->timer, p->timetik, (void*)mlx_tick_handler, (uint32_t)&mlx90614drv);
+ rtl_printf("MLX90614 Timer Period = %u us\n", p->timetik);
+ p->init = 1;
+ }
+}
+
+void mlx90614_deinit(void)
+{
+ PMLX90614DRV p = &mlx90614drv;
+ i2c_drv_t *pi2c = &p->i2c;
+ if(p->init > 0) {
+ rtl_printf("Deinit MLX90614\n");
+ gtimer_stop(&p->timer);
+ gtimer_deinit(&p->timer);
+// (!) Не используется mlx90614_write / mlx90614_read для сокращения кода
+// mlx90614_write(MLX90614_REG_CONFIG, MLX90614_CONFIG_MODE_POWERDOWN);
+ // Break controller.
+ i2c_reg(REG_DW_I2C_IC_ENABLE) |= 2;
+ vTaskDelay(2); // +WDT
+ // Disable controller.
+ i2c_reg(REG_DW_I2C_IC_ENABLE) = 0;
+/* Exit from Sleep Mode > 250 ms !
+ vTaskDelay(2); // +WDT
+ // Master Target Address
+ i2c_reg(REG_DW_I2C_IC_TAR) = p->addr;
+ // Enable controller.
+ i2c_reg(REG_DW_I2C_IC_ENABLE) = BIT_IC_ENABLE;
+ // Заполним FIFO ic I2C командой sleep MLX90614
+ vTaskDelay(2); // +WDT
+ // MLX90614 Enter Sleep Mode
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = MLX90614_SLEEP | BIT_IC_DATA_CMD_STOP;
+*/
+ vTaskDelay(2); // +WDT
+ _i2c_deinit(&p->i2c);
+ if(p->pbuf) {
+ free(p->pbuf);
+ p->pbuf = NULL;
+ }
+ }
+ p->init = 0;
+}
+
+LOCAL void ShowMlx(void)
+{
+ PMLX90614DRV p = &mlx90614drv;
+ rtl_printf("MLX90614: %d, %d\n", p->buf_i2c.us[0], p->buf_i2c.ss[1]);
+ rtl_printf("MLX90614: Cnt = %u, Err = %u\n", p->count, p->errs);
+}
+
+LOCAL void fATMLX(int argc, char *argv[])
+{
+ if(argc > 1) {
+ if(atoi(argv[1])) {
+ mlx90614_init();
+ vTaskDelay(10); // +WDT
+ }
+ else mlx90614_deinit();
+ }
+ ShowMlx();
+}
+
+
+MON_RAM_TAB_SECTION COMMAND_TABLE console_commands_mlx90614[] = {
+ {"ATMLX", 0, fATMLX, "=[0/1]: MLX90614 =1 start, =0 stop"}
+};
+/*
+ * Test i2c:
+ * ati2c i
+ * ati2c g 5a 1 6 3
+ * ati2c d
+ */
diff --git a/RTLGDB/Project/MPU6050/MPU6050.c b/RTLGDB/Project/MPU6050/MPU6050.c
new file mode 100644
index 0000000..642d041
--- /dev/null
+++ b/RTLGDB/Project/MPU6050/MPU6050.c
@@ -0,0 +1,223 @@
+#include "MPU6050.h"
+#include "kalman.h"
+
+MPU6050_DataPack dataPack1[MPU6050_PACKSIZE], dataPack2[MPU6050_PACKSIZE];
+uint16_t currentDataPackPointer = 0;
+uint8_t currentDataPack = 0;
+uint8_t previousDataPackReady = 0;
+
+MPU6050_Data mpu =
+{
+ .i2c.idx = 3, // I2C3
+ .i2c.io_sel = S0, // PB_2, PB_3
+ .i2c.mode = DRV_I2C_FS_MODE,
+};
+
+void MPU6050T_irq_handler(uint32_t *par)
+{
+ MPU6050_Data_p p = &mpu;
+
+ // MPU6050_ReadGyroscope
+ uint8_t data[2];
+ data[0] = MPU6050_GYRO_XOUT_H; // MPU6050_ACCEL_XOUT_H;// MPU6050_GYRO_XOUT_H;
+ _i2c_write(&p->i2c, MPU6050_I2C_ADDR, &data[0], 1, 0);
+ _i2c_read(&p->i2c, MPU6050_I2C_ADDR, &data, 2, 1);
+
+ p->Gyro_X = (int16_t)(data[0] << 8 | data[1]);
+
+ data[0] = MPU6050_ACCEL_XOUT_H;
+ _i2c_write(&p->i2c, MPU6050_I2C_ADDR, &data[0], 1, 0);
+ _i2c_read(&p->i2c, MPU6050_I2C_ADDR, &data, 2, 1);
+
+ p->Accel_X = (int16_t)(data[0] << 8 | data[1]);
+
+ if (currentDataPack)
+ {
+ dataPack2[currentDataPackPointer].X = Kalman_GetAngle(p->Accel_X, p->Gyro_X, 0.001);
+ }
+ else
+ {
+ dataPack1[currentDataPackPointer].X = Kalman_GetAngle(p->Accel_X, p->Gyro_X, 0.001);
+ }
+
+ currentDataPackPointer++;
+ if (currentDataPackPointer >= MPU6050_PACKSIZE)
+ {
+ currentDataPackPointer = 0;
+ currentDataPack = !currentDataPack;
+ previousDataPackReady = 1;
+ }
+}
+
+int16_t MPU6050_Init()
+{
+ MPU6050_Data_p p = &mpu;
+ uint8_t temp;
+ uint8_t d[2];
+
+ Kalman_Init();
+
+ _i2c_init(&p->i2c);
+
+ d[0] = MPU6050_PWR_MGMT_1;
+ d[1] = 0x00;
+ _i2c_write(&p->i2c, MPU6050_I2C_ADDR, &d, 2, 1);
+
+
+ temp = MPU6050_WHO_AM_I;
+ _i2c_write(&p->i2c, MPU6050_I2C_ADDR, &temp, 1, 0);
+ _i2c_read(&p->i2c, MPU6050_I2C_ADDR, &temp, 1, 1);
+
+ if (temp != MPU6050_I_AM)
+ {
+ DiagPrintf("MPU6050. Init Error. ID = %d (default:%d)\n", temp, MPU6050_I_AM);
+ return MPU6050_RESULT_ERROR;
+ }
+ else
+ {
+ DiagPrintf("MPU6050. Init Done. ID = %d\n", temp);
+ }
+
+ MPU6050_SetDataRate(MPU6050_DataRate_8KHz);
+ MPU6050_SetAccelerometer(MPU6050_Accelerometer_2G);
+ MPU6050_SetGyroscope(MPU6050_Gyroscope_250s);
+ MPU6050_SetDLPF(MPU6050_Bandwidth_Infinity);
+
+ MPU6050_OffsetCalibrate(2000);
+
+ gtimer_init(&p->timer, MPU6050_IRQTIMER);
+ gtimer_start_periodical(&p->timer, MPU6050_PERIOD_US, (void*)MPU6050T_irq_handler, (uint32_t)&mpu);
+
+ return MPU6050_RESULT_OK;
+}
+
+void MPU6050_SetGyroscope(MPU6050_Gyroscope gs)
+{
+ MPU6050_Data_p p = &mpu;
+ uint8_t temp;
+ temp = MPU6050_GYRO_CONFIG;
+ _i2c_write(&p->i2c, MPU6050_I2C_ADDR, &temp, 1, 0);
+ _i2c_read(&p->i2c, MPU6050_I2C_ADDR, &temp, 1, 1);
+
+ temp = (temp & 0xE7) | (uint8_t)gs << 3;
+ _i2c_write(&p->i2c, MPU6050_I2C_ADDR, &temp, 1, 1);
+}
+
+void MPU6050_SetAccelerometer(MPU6050_Accelerometer as)
+{
+ MPU6050_Data_p p = &mpu;
+ uint8_t temp;
+ temp = MPU6050_ACCEL_CONFIG;
+ _i2c_write(&p->i2c, MPU6050_I2C_ADDR, &temp, 1, 0);
+ _i2c_read(&p->i2c, MPU6050_I2C_ADDR, &temp, 1, 1);
+
+ temp = (temp & 0xE7) | (uint8_t)as << 3;
+ _i2c_write(&p->i2c, MPU6050_I2C_ADDR, &temp, 1, 1);
+}
+
+void MPU6050_SetDataRate(uint8_t rate)
+{
+ MPU6050_Data_p p = &mpu;
+ uint8_t d[2];
+
+ d[0] = MPU6050_SMPLRT_DIV;
+ d[1] = rate;
+
+ _i2c_write(&p->i2c, MPU6050_I2C_ADDR, &d, 2, 1);
+}
+int16_t MPU6050_IsDataPacketReady(MPU6050_DataPack *dp)
+{
+ if (previousDataPackReady)
+ {
+ previousDataPackReady = 0;
+
+ if (currentDataPack)
+ {
+ memcpy(dp, &dataPack1, sizeof(MPU6050_DataPack) * MPU6050_PACKSIZE);
+ }
+ else
+ {
+ memcpy(dp, &dataPack2, sizeof(MPU6050_DataPack) * MPU6050_PACKSIZE);
+ }
+ return MPU6050_RESULT_OK;
+ }
+
+ return MPU6050_RESULT_NO;
+}
+
+void MPU6050_OffsetCalibrate(int32_t num)
+{
+ MPU6050_Data_p p = &mpu;
+ int32_t x = 0, y = 0, z = 0, i;
+ uint8_t data[6];
+
+ DiagPrintf("MPU6050. Calibrating gyroscope, don't move the hardware!\n");
+ //vTaskDelay(500);
+
+ data[0] = MPU6050_GYRO_XOUT_H;
+ _i2c_write(&p->i2c, MPU6050_I2C_ADDR, &data[0], 1, 0);
+ _i2c_read(&p->i2c, MPU6050_I2C_ADDR, &data, 6, 1);
+
+ x = (int16_t)(data[0] << 8 | data[1]);
+ y = (int16_t)(data[2] << 8 | data[3]);
+ z = (int16_t)(data[4] << 8 | data[5]);
+
+ for (i = 0; i < num; i++)
+ {
+ data[0] = MPU6050_GYRO_XOUT_H;
+ _i2c_write(&p->i2c, MPU6050_I2C_ADDR, &data[0], 1, 0);
+ _i2c_read(&p->i2c, MPU6050_I2C_ADDR, &data, 6, 1);
+
+ x = (x + (int16_t)(data[0] << 8 | data[1])) / 2;
+ y = (y + (int16_t)(data[2] << 8 | data[3])) / 2;
+ z = (z + (int16_t)(data[4] << 8 | data[5])) / 2;
+ }
+
+ //gyro_x_OC = x;
+ //gyro_y_OC = y;
+ //gyro_z_OC = z;
+
+ DiagPrintf("MPU6050. Gyroscope offsets: X = %d Y = %d Z = %d\n", x, y, z);
+
+ data[0] = MPU6050_ACCEL_XOUT_H;
+ _i2c_write(&p->i2c, MPU6050_I2C_ADDR, &data[0], 1, 0);
+ _i2c_read(&p->i2c, MPU6050_I2C_ADDR, &data, 6, 1);
+
+ DiagPrintf("MPU6050. Calibrating accelrometer, don't move the hardware!\n");
+
+ x = (int16_t)(data[0] << 8 | data[1]);
+ y = (int16_t)(data[2] << 8 | data[3]);
+ z = (int16_t)(data[4] << 8 | data[5]);
+
+ for (i = 0; i < num; i++)
+ {
+ data[0] = MPU6050_ACCEL_XOUT_H;
+ _i2c_write(&p->i2c, MPU6050_I2C_ADDR, &data[0], 1, 0);
+ _i2c_read(&p->i2c, MPU6050_I2C_ADDR, &data, 6, 1);
+
+ x = (x + (int16_t)(data[0] << 8 | data[1])) / 2;
+ y = (y + (int16_t)(data[2] << 8 | data[3])) / 2;
+ z = (z + (int16_t)(data[4] << 8 | data[5])) / 2;
+ }
+
+ //accel_x_OC = x;
+ //accel_y_OC = y;
+ //accel_z_OC = z - (float)g * 1000 / accel_scale_fact;
+
+ DiagPrintf("MPU6050. Accelrometer offsets: X = %d Y = %d Z = %d\n", x, y, z);
+}
+
+void MPU6050_SetDLPF(uint8_t Bandwidth)
+{
+ MPU6050_Data_p p = &mpu;
+ uint8_t data[2];
+
+ if (Bandwidth < MPU6050_Bandwidth_Infinity || Bandwidth > MPU6050_Bandwidth_5Hz)
+ {
+ Bandwidth = MPU6050_Bandwidth_Infinity;
+ }
+
+ data[0] = MPU6050_CONFIG;
+ data[1] = Bandwidth;
+ _i2c_write(&p->i2c, MPU6050_I2C_ADDR, &data[0], 2, 1);
+}
diff --git a/RTLGDB/Project/MPU6050/MPU6050.h b/RTLGDB/Project/MPU6050/MPU6050.h
new file mode 100644
index 0000000..c2e978d
--- /dev/null
+++ b/RTLGDB/Project/MPU6050/MPU6050.h
@@ -0,0 +1,140 @@
+#ifndef _MPU6050_H_
+#define _MPU6050_H_
+
+#include "FreeRTOS.h"
+#include "device.h"
+#include "rtl8195a/rtl_libc.h"
+#include "platform_stdlib.h"
+
+#include "timer_api.h"
+#include "driver/i2c_drv.h"
+#include "pinmap.h"
+
+#define MPU6050_IRQTIMER TIMER0
+#define MPU6050_I2C_ADDR 0x68
+#define MPU6050_PACKSIZE 4096
+#define MPU6050_PERIOD_US 1000
+
+typedef struct _MPU6050_Data
+{
+ // Приватные
+ i2c_drv_t i2c;
+ gtimer_t timer;
+
+ // Публичные
+ int16_t Accel_X;
+ int16_t Accel_Y;
+ int16_t Accel_Z;
+ int16_t Gyro_X;
+ int16_t Gyro_Y;
+ int16_t Gyro_Z;
+ float Temp_Deg;
+} MPU6050_Data, *MPU6050_Data_p;
+
+typedef struct
+{
+ double X;
+ //int16_t Y;
+ //int16_t Z;
+} MPU6050_DataPack;
+
+typedef enum
+{
+ MPU6050_Accelerometer_2G = 0x00,
+ MPU6050_Accelerometer_4G = 0x01,
+ MPU6050_Accelerometer_8G = 0x02,
+ MPU6050_Accelerometer_16G = 0x03
+} MPU6050_Accelerometer;
+
+typedef enum
+{
+ MPU6050_Bandwidth_Infinity = 0x00,
+ MPU6050_Bandwidth_184Hz = 0x01,
+ MPU6050_Bandwidth_94Hz = 0x02,
+ MPU6050_Bandwidth_44Hz = 0x03,
+ MPU6050_Bandwidth_21Hz = 0x04,
+ MPU6050_Bandwidth_10Hz = 0x05,
+ MPU6050_Bandwidth_5Hz = 0x06,
+} MPU6050_DLFP;
+
+typedef enum
+{
+ MPU6050_Gyroscope_250s = 0x00,
+ MPU6050_Gyroscope_500s = 0x01,
+ MPU6050_Gyroscope_1000s = 0x02,
+ MPU6050_Gyroscope_2000s = 0x03
+} MPU6050_Gyroscope;
+
+typedef enum
+{
+ MPU6050_RESULT_OK = 1,
+ MPU6050_RESULT_NO = 0,
+ MPU6050_RESULT_ERROR = -1,
+ MPU6050_RESULT_DEVNOTCONN = -2
+} MPU6050_Result;
+
+#define MPU6050_DataRate_8KHz 0
+#define MPU6050_DataRate_4KHz 1
+#define MPU6050_DataRate_2KHz 3
+#define MPU6050_DataRate_1KHz 7
+#define MPU6050_DataRate_500Hz 15
+#define MPU6050_DataRate_250Hz 31
+#define MPU6050_DataRate_125Hz 63
+#define MPU6050_DataRate_100Hz 79
+
+#define MPU6050_AUX_VDDIO 0x01
+#define MPU6050_SMPLRT_DIV 0x19
+#define MPU6050_CONFIG 0x1A
+#define MPU6050_GYRO_CONFIG 0x1B
+#define MPU6050_ACCEL_CONFIG 0x1C
+#define MPU6050_MOTION_THRESH 0x1F
+#define MPU6050_INT_PIN_CFG 0x37
+#define MPU6050_INT_ENABLE 0x38
+#define MPU6050_INT_STATUS 0x3A
+#define MPU6050_ACCEL_XOUT_H 0x3B
+#define MPU6050_ACCEL_XOUT_L 0x3C
+#define MPU6050_ACCEL_YOUT_H 0x3D
+#define MPU6050_ACCEL_YOUT_L 0x3E
+#define MPU6050_ACCEL_ZOUT_H 0x3F
+#define MPU6050_ACCEL_ZOUT_L 0x40
+#define MPU6050_TEMP_OUT_H 0x41
+#define MPU6050_TEMP_OUT_L 0x42
+#define MPU6050_GYRO_XOUT_H 0x43
+#define MPU6050_GYRO_XOUT_L 0x44
+#define MPU6050_GYRO_YOUT_H 0x45
+#define MPU6050_GYRO_YOUT_L 0x46
+#define MPU6050_GYRO_ZOUT_H 0x47
+#define MPU6050_GYRO_ZOUT_L 0x48
+#define MPU6050_MOT_DETECT_STATUS 0x61
+#define MPU6050_SIGNAL_PATH_RESET 0x68
+#define MPU6050_MOT_DETECT_CTRL 0x69
+#define MPU6050_USER_CTRL 0x6A
+#define MPU6050_PWR_MGMT_1 0x6B
+#define MPU6050_PWR_MGMT_2 0x6C
+#define MPU6050_FIFO_COUNTH 0x72
+#define MPU6050_FIFO_COUNTL 0x73
+#define MPU6050_FIFO_R_W 0x74
+#define MPU6050_WHO_AM_I 0x75
+#define MPU6050_I_AM 0x68
+
+// Gyro sensitivities in degrees/s
+#define MPU6050_GYRO_SENS_250 ((double) 131.0)
+#define MPU6050_GYRO_SENS_500 ((double) 65.5)
+#define MPU6050_GYRO_SENS_1000 ((double) 32.8)
+#define MPU6050_GYRO_SENS_2000 ((double) 16.4)
+
+// Acce sensitivities in g/s
+#define MPU6050_ACCE_SENS_2 ((double) 16384.0)
+#define MPU6050_ACCE_SENS_4 ((double) 8192.0)
+#define MPU6050_ACCE_SENS_8 ((double) 4096.0)
+#define MPU6050_ACCE_SENS_16 ((double) 2048.0)
+
+int16_t MPU6050_Init();
+void MPU6050_SetGyroscope(MPU6050_Gyroscope gs);
+void MPU6050_SetAccelerometer(MPU6050_Accelerometer as);
+void MPU6050_SetDataRate(uint8_t rate);
+int16_t MPU6050_IsDataPacketReady(MPU6050_DataPack *dp);
+void MPU6050_OffsetCalibrate(int32_t num);
+void MPU6050_SetDLPF(uint8_t Bandwidth);
+
+#endif // _MPU6050_H_
diff --git a/RTLGDB/Project/MPU6050/kalman.c b/RTLGDB/Project/MPU6050/kalman.c
new file mode 100644
index 0000000..93e97ce
--- /dev/null
+++ b/RTLGDB/Project/MPU6050/kalman.c
@@ -0,0 +1,65 @@
+#include "kalman.h"
+
+const double Q_angle = 0.01;
+const double Q_bias = 0.003;
+const double R_measure = 0.03;
+
+static double angle;
+static double bias;
+static double rate;
+
+double P[2][2];
+double K[2];
+double y;
+double S;
+
+void Kalman_Init()
+{
+ bias = 0;
+ rate = 0;
+ angle = 180;
+
+ P[0][0] = 0;
+ P[0][1] = 0;
+ P[1][0] = 0;
+ P[1][1] = 0;
+}
+
+// Угол в градусах и угловая скорость в градус\сек, период в секундах.
+double Kalman_GetAngle(double newAngle, double newRate, double dt)
+{
+ // Step 1
+ rate = newRate - bias;
+ angle += dt * rate;
+
+ // Update estimation error covariance - Project the error covariance ahead
+ // Step 2
+ P[0][0] += dt * (dt*P[1][1] - P[0][1] - P[1][0] + Q_angle);
+ P[0][1] -= dt * P[1][1];
+ P[1][0] -= dt * P[1][1];
+ P[1][1] += Q_bias * dt;
+
+ // Discrete Kalman filter measurement update equations - Measurement Update ("Correct")
+ // Calculate Kalman gain - Compute the Kalman gain
+ // Step 4
+ S = P[0][0] + R_measure;
+ // Step 5
+ K[0] = P[0][0] / S;
+ K[1] = P[1][0] / S;
+
+ // Calculate angle and bias - Update estimate with measurement zk(newAngle)
+ // Step 3
+ y = newAngle - angle;
+ // Step 6
+ angle += K[0] * y;
+ bias += K[1] * y;
+
+ // Calculate estimation error covariance - Update the error covariance
+ // Step 7
+ P[0][0] -= K[0] * P[0][0];
+ P[0][1] -= K[0] * P[0][1];
+ P[1][0] -= K[1] * P[0][0];
+ P[1][1] -= K[1] * P[0][1];
+
+ return angle;
+}
\ No newline at end of file
diff --git a/RTLGDB/Project/MPU6050/kalman.h b/RTLGDB/Project/MPU6050/kalman.h
new file mode 100644
index 0000000..a063eda
--- /dev/null
+++ b/RTLGDB/Project/MPU6050/kalman.h
@@ -0,0 +1,12 @@
+#ifndef _KALMAN_H_
+#define _KALMAN_H_
+
+#include "FreeRTOS.h"
+#include "device.h"
+#include "rtl8195a/rtl_libc.h"
+#include "platform_stdlib.h"
+
+void Kalman_Init();
+double Kalman_GetAngle(double newAngle, double newRate, double dt);
+
+#endif // _KALMAN_H_
diff --git a/RTLGDB/Project/SSD1306/SSD1306.c b/RTLGDB/Project/SSD1306/SSD1306.c
new file mode 100644
index 0000000..28fce79
--- /dev/null
+++ b/RTLGDB/Project/SSD1306/SSD1306.c
@@ -0,0 +1,498 @@
+#include "SSD1306.h"
+#include "FreeRTOS.h"
+
+i2c_t SSD1306_i2c;
+//i2c_drv_t SSD1306_i2c;
+
+// SSD1306 data buffer
+static uint8_t SSD1306_Buffer[SSD1306_WIDTH * SSD1306_HEIGHT / 8];
+static SSD1306_t SSD1306;
+
+void SSD1306_I2C_WriteMulti(uint8_t reg, uint8_t* data, uint16_t count)
+{
+ uint8_t datasend[count + 1];
+
+ datasend[0] = reg;
+ for (int i = 0; i= SSD1306_WIDTH || y >= SSD1306_HEIGHT)
+ {
+ return;
+ }
+
+ if (SSD1306.Inverted)
+ {
+ color = (SSD1306_COLOR_t)!color;
+ }
+
+ if (color == SSD1306_COLOR_WHITE)
+ {
+ SSD1306_Buffer[x + (y / 8) * SSD1306_WIDTH] |= 1 << (y % 8);
+ }
+ else
+ {
+ SSD1306_Buffer[x + (y / 8) * SSD1306_WIDTH] &= ~(1 << (y % 8));
+ }
+}
+
+void SSD1306_GotoXY(uint16_t x, uint16_t y)
+{
+ SSD1306.CurrentX = x;
+ SSD1306.CurrentY = y;
+}
+
+char SSD1306_Putc(char ch, FontDef_t* Font, SSD1306_COLOR_t color)
+{
+ uint32_t i, b, j;
+
+ // Check available space in LCD
+ if(SSD1306_WIDTH <= (SSD1306.CurrentX + Font->FontWidth) || SSD1306_HEIGHT <= (SSD1306.CurrentY + Font->FontHeight))
+ {
+ return 0;
+ }
+
+ for (i = 0; i < Font->FontHeight; i++)
+ {
+ b = Font->data[(ch - 32) * Font->FontHeight + i];
+ for (j = 0; j < Font->FontWidth; j++)
+ {
+ if ((b << j) & 0x8000)
+ {
+ SSD1306_DrawPixel(SSD1306.CurrentX + j, (SSD1306.CurrentY + i), (SSD1306_COLOR_t) color);
+ }
+ else
+ {
+ SSD1306_DrawPixel(SSD1306.CurrentX + j, (SSD1306.CurrentY + i), (SSD1306_COLOR_t)!color);
+ }
+ }
+ }
+
+ SSD1306.CurrentX += Font->FontWidth;
+ return ch;
+}
+
+char SSD1306_Puts(char* str, FontDef_t* Font, SSD1306_COLOR_t color)
+{
+ while (*str)
+ {
+ if (SSD1306_Putc(*str, Font, color) != *str)
+ {
+ return *str; // Error
+ }
+ str++;
+ }
+
+ return *str; // Ok
+}
+
+
+void SSD1306_DrawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, SSD1306_COLOR_t c)
+{
+ int16_t dx, dy, sx, sy, err, e2, i, tmp;
+
+ if(x0 >= SSD1306_WIDTH)
+ {
+ x0 = SSD1306_WIDTH - 1;
+ }
+ if(x1 >= SSD1306_WIDTH)
+ {
+ x1 = SSD1306_WIDTH - 1;
+ }
+ if(y0 >= SSD1306_HEIGHT)
+ {
+ y0 = SSD1306_HEIGHT - 1;
+ }
+ if(y1 >= SSD1306_HEIGHT)
+ {
+ y1 = SSD1306_HEIGHT - 1;
+ }
+
+ dx = (x0 < x1) ? (x1 - x0) : (x0 - x1);
+ dy = (y0 < y1) ? (y1 - y0) : (y0 - y1);
+ sx = (x0 < x1) ? 1 : -1;
+ sy = (y0 < y1) ? 1 : -1;
+ err = ((dx > dy) ? dx : -dy) / 2;
+
+ if(dx == 0)
+ {
+ if(y1 < y0)
+ {
+ tmp = y1;
+ y1 = y0;
+ y0 = tmp;
+ }
+
+ if(x1 < x0)
+ {
+ tmp = x1;
+ x1 = x0;
+ x0 = tmp;
+ }
+
+ // Vertical line
+ for(i = y0; i <= y1; i++)
+ {
+ SSD1306_DrawPixel(x0, i, c);
+ }
+
+ return;
+ }
+
+ if(dy == 0)
+ {
+ if (y1 < y0)
+ {
+ tmp = y1;
+ y1 = y0;
+ y0 = tmp;
+ }
+
+ if (x1 < x0)
+ {
+ tmp = x1;
+ x1 = x0;
+ x0 = tmp;
+ }
+
+ // Horizontal line
+ for (i = x0; i <= x1; i++)
+ {
+ SSD1306_DrawPixel(i, y0, c);
+ }
+
+ return;
+ }
+
+ while (1)
+ {
+ SSD1306_DrawPixel(x0, y0, c);
+ if (x0 == x1 && y0 == y1)
+ {
+ break;
+ }
+ e2 = err;
+ if (e2 > -dx)
+ {
+ err -= dy;
+ x0 += sx;
+ }
+ if (e2 < dy)
+ {
+ err += dx;
+ y0 += sy;
+ }
+ }
+}
+
+void SSD1306_DrawRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h, SSD1306_COLOR_t c)
+{
+ if (x >= SSD1306_WIDTH || y >= SSD1306_HEIGHT)
+ {
+ return;
+ }
+
+ if ((x + w) >= SSD1306_WIDTH)
+ {
+ w = SSD1306_WIDTH - x;
+ }
+ if ((y + h) >= SSD1306_HEIGHT)
+ {
+ h = SSD1306_HEIGHT - y;
+ }
+
+ SSD1306_DrawLine(x, y, x + w, y, c); //Top line
+ SSD1306_DrawLine(x, y + h, x + w, y + h, c); // Bottom line
+ SSD1306_DrawLine(x, y, x, y + h, c); // Left line
+ SSD1306_DrawLine(x + w, y, x + w, y + h, c); // Right line
+}
+
+void SSD1306_DrawFilledRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h, SSD1306_COLOR_t c)
+{
+ uint8_t i;
+
+ if(x >= SSD1306_WIDTH || y >= SSD1306_HEIGHT)
+ {
+ return;
+ }
+
+ if ((x + w) >= SSD1306_WIDTH)
+ {
+ w = SSD1306_WIDTH - x;
+ }
+ if ((y + h) >= SSD1306_HEIGHT)
+ {
+ h = SSD1306_HEIGHT - y;
+ }
+
+ for (i = 0; i <= h; i++)
+ {
+ SSD1306_DrawLine(x, y + i, x + w, y + i, c);
+ }
+}
+
+void SSD1306_DrawTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, SSD1306_COLOR_t color)
+{
+ SSD1306_DrawLine(x1, y1, x2, y2, color);
+ SSD1306_DrawLine(x2, y2, x3, y3, color);
+ SSD1306_DrawLine(x3, y3, x1, y1, color);
+}
+
+
+void SSD1306_DrawFilledTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, SSD1306_COLOR_t color)
+{
+ int16_t deltax = 0, deltay = 0, x = 0, y = 0, xinc1 = 0, xinc2 = 0,
+ yinc1 = 0, yinc2 = 0, den = 0, num = 0, numadd = 0, numpixels = 0,
+ curpixel = 0;
+
+ deltax = ABS(x2 - x1);
+ deltay = ABS(y2 - y1);
+ x = x1;
+ y = y1;
+
+ if(x2 >= x1)
+ {
+ xinc1 = 1;
+ xinc2 = 1;
+ }
+ else
+ {
+ xinc1 = -1;
+ xinc2 = -1;
+ }
+
+ if(y2 >= y1)
+ {
+ yinc1 = 1;
+ yinc2 = 1;
+ }
+ else
+ {
+ yinc1 = -1;
+ yinc2 = -1;
+ }
+
+ if(deltax >= deltay)
+ {
+ xinc1 = 0;
+ yinc2 = 0;
+ den = deltax;
+ num = deltax / 2;
+ numadd = deltay;
+ numpixels = deltax;
+ }
+ else
+ {
+ xinc2 = 0;
+ yinc1 = 0;
+ den = deltay;
+ num = deltay / 2;
+ numadd = deltax;
+ numpixels = deltay;
+ }
+
+ for (curpixel = 0; curpixel <= numpixels; curpixel++)
+ {
+ SSD1306_DrawLine(x, y, x3, y3, color);
+
+ num += numadd;
+ if (num >= den)
+ {
+ num -= den;
+ x += xinc1;
+ y += yinc1;
+ }
+ x += xinc2;
+ y += yinc2;
+ }
+}
+
+void SSD1306_DrawCircle(int16_t x0, int16_t y0, int16_t r, SSD1306_COLOR_t c)
+{
+ int16_t f = 1 - r;
+ int16_t ddF_x = 1;
+ int16_t ddF_y = -2 * r;
+ int16_t x = 0;
+ int16_t y = r;
+
+ SSD1306_DrawPixel(x0, y0 + r, c);
+ SSD1306_DrawPixel(x0, y0 - r, c);
+ SSD1306_DrawPixel(x0 + r, y0, c);
+ SSD1306_DrawPixel(x0 - r, y0, c);
+
+ while (x < y)
+ {
+ if (f >= 0)
+ {
+ y--;
+ ddF_y += 2;
+ f += ddF_y;
+ }
+ x++;
+ ddF_x += 2;
+ f += ddF_x;
+
+ SSD1306_DrawPixel(x0 + x, y0 + y, c);
+ SSD1306_DrawPixel(x0 - x, y0 + y, c);
+ SSD1306_DrawPixel(x0 + x, y0 - y, c);
+ SSD1306_DrawPixel(x0 - x, y0 - y, c);
+
+ SSD1306_DrawPixel(x0 + y, y0 + x, c);
+ SSD1306_DrawPixel(x0 - y, y0 + x, c);
+ SSD1306_DrawPixel(x0 + y, y0 - x, c);
+ SSD1306_DrawPixel(x0 - y, y0 - x, c);
+ }
+}
+
+void SSD1306_DrawFilledCircle(int16_t x0, int16_t y0, int16_t r, SSD1306_COLOR_t c)
+{
+ int16_t f = 1 - r;
+ int16_t ddF_x = 1;
+ int16_t ddF_y = -2 * r;
+ int16_t x = 0;
+ int16_t y = r;
+
+ SSD1306_DrawPixel(x0, y0 + r, c);
+ SSD1306_DrawPixel(x0, y0 - r, c);
+ SSD1306_DrawPixel(x0 + r, y0, c);
+ SSD1306_DrawPixel(x0 - r, y0, c);
+ SSD1306_DrawLine(x0 - r, y0, x0 + r, y0, c);
+
+ while (x < y)
+ {
+ if (f >= 0)
+ {
+ y--;
+ ddF_y += 2;
+ f += ddF_y;
+ }
+ x++;
+ ddF_x += 2;
+ f += ddF_x;
+
+ SSD1306_DrawLine(x0 - x, y0 + y, x0 + x, y0 + y, c);
+ SSD1306_DrawLine(x0 + x, y0 - y, x0 - x, y0 - y, c);
+
+ SSD1306_DrawLine(x0 + y, y0 + x, x0 - y, y0 + x, c);
+ SSD1306_DrawLine(x0 + y, y0 - x, x0 - y, y0 - x, c);
+ }
+}
+
+void SSD1306_ON(void)
+{
+ SSD1306_WRITECOMMAND(0x8D);
+ SSD1306_WRITECOMMAND(0x14);
+ SSD1306_WRITECOMMAND(0xAF);
+}
+
+void SSD1306_OFF(void)
+{
+ SSD1306_WRITECOMMAND(0x8D);
+ SSD1306_WRITECOMMAND(0x10);
+ SSD1306_WRITECOMMAND(0xAE);
+}
diff --git a/RTLGDB/Project/SSD1306/SSD1306.h b/RTLGDB/Project/SSD1306/SSD1306.h
new file mode 100644
index 0000000..5c8b7f3
--- /dev/null
+++ b/RTLGDB/Project/SSD1306/SSD1306.h
@@ -0,0 +1,65 @@
+#ifndef _SSD1306_H_
+#define _SSD1306_H_
+
+#include "device.h"
+#include "fonts.h"
+
+#include "stdlib.h"
+#include "string.h"
+
+#include "i2c_api.h"
+#include "pinmap.h"
+#include "ex_api.h"
+
+#include "driver/i2c_drv.h"
+
+#define SSD1306_I2C_PIN_SDA PC_4
+#define SSD1306_I2C_PIN_SCL PC_5
+#define SSD1306_I2C_BUS_CLK 1000000 //hz
+
+// I2C address
+#ifndef SSD1306_I2C_ADDR
+#define SSD1306_I2C_ADDR (0x78 >> 1)
+//#define SSD1306_I2C_ADDR 0x7A
+#endif
+
+// SSD1306 settings
+#ifndef SSD1306_WIDTH
+#define SSD1306_WIDTH 128
+#endif
+#ifndef SSD1306_HEIGHT
+#define SSD1306_HEIGHT 64
+#endif
+
+typedef enum {
+ SSD1306_COLOR_BLACK = 0x00,
+ SSD1306_COLOR_WHITE = 0x01
+} SSD1306_COLOR_t;
+
+typedef struct {
+ uint16_t CurrentX;
+ uint16_t CurrentY;
+ uint8_t Inverted;
+ uint8_t Initialized;
+} SSD1306_t;
+
+#define SSD1306_WRITECOMMAND(command) SSD1306_I2C_Write(0x00, (command))
+#define SSD1306_WRITEDATA(data) SSD1306_I2C_Write(0x40, (data))
+#define ABS(x) ((x) > 0 ? (x) : -(x))
+
+uint8_t SSD1306_Init(i2c_t *i2c);
+void SSD1306_UpdateScreen(void);
+void SSD1306_ToggleInvert(void);
+void SSD1306_Fill(SSD1306_COLOR_t Color);
+void SSD1306_DrawPixel(uint16_t x, uint16_t y, SSD1306_COLOR_t color);
+void SSD1306_GotoXY(uint16_t x, uint16_t y);
+char SSD1306_Putc(char ch, FontDef_t* Font, SSD1306_COLOR_t color);
+char SSD1306_Puts(char* str, FontDef_t* Font, SSD1306_COLOR_t color);
+void SSD1306_DrawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, SSD1306_COLOR_t c);
+void SSD1306_DrawRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h, SSD1306_COLOR_t c);
+void SSD1306_DrawFilledRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h, SSD1306_COLOR_t c);
+void SSD1306_DrawTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, SSD1306_COLOR_t color);
+void SSD1306_DrawCircle(int16_t x0, int16_t y0, int16_t r, SSD1306_COLOR_t c);
+void SSD1306_DrawFilledCircle(int16_t x0, int16_t y0, int16_t r, SSD1306_COLOR_t c);
+
+#endif // _SSD1306_H_
diff --git a/RTLGDB/Project/SSD1306/fonts.c b/RTLGDB/Project/SSD1306/fonts.c
new file mode 100644
index 0000000..c517890
--- /dev/null
+++ b/RTLGDB/Project/SSD1306/fonts.c
@@ -0,0 +1,345 @@
+/**
+ * original author: Tilen Majerle
+ * modification for STM32f10x: Alexander Lutsai
+
+ ----------------------------------------------------------------------
+ Copyright (C) Alexander Lutsai, 2016
+ Copyright (C) Tilen Majerle, 2015
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ ----------------------------------------------------------------------
+ */
+#include "fonts.h"
+
+const uint16_t Font7x10 [] = {
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // sp
+0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x1000, 0x0000, 0x0000, // !
+0x2800, 0x2800, 0x2800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // "
+0x2400, 0x2400, 0x7C00, 0x2400, 0x4800, 0x7C00, 0x4800, 0x4800, 0x0000, 0x0000, // #
+0x3800, 0x5400, 0x5000, 0x3800, 0x1400, 0x5400, 0x5400, 0x3800, 0x1000, 0x0000, // $
+0x2000, 0x5400, 0x5800, 0x3000, 0x2800, 0x5400, 0x1400, 0x0800, 0x0000, 0x0000, // %
+0x1000, 0x2800, 0x2800, 0x1000, 0x3400, 0x4800, 0x4800, 0x3400, 0x0000, 0x0000, // &
+0x1000, 0x1000, 0x1000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // '
+0x0800, 0x1000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x1000, 0x0800, // (
+0x2000, 0x1000, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x1000, 0x2000, // )
+0x1000, 0x3800, 0x1000, 0x2800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // *
+0x0000, 0x0000, 0x1000, 0x1000, 0x7C00, 0x1000, 0x1000, 0x0000, 0x0000, 0x0000, // +
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1000, 0x1000, 0x1000, // ,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3800, 0x0000, 0x0000, 0x0000, 0x0000, // -
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x0000, // .
+0x0800, 0x0800, 0x1000, 0x1000, 0x1000, 0x1000, 0x2000, 0x2000, 0x0000, 0x0000, // /
+0x3800, 0x4400, 0x4400, 0x5400, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // 0
+0x1000, 0x3000, 0x5000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // 1
+0x3800, 0x4400, 0x4400, 0x0400, 0x0800, 0x1000, 0x2000, 0x7C00, 0x0000, 0x0000, // 2
+0x3800, 0x4400, 0x0400, 0x1800, 0x0400, 0x0400, 0x4400, 0x3800, 0x0000, 0x0000, // 3
+0x0800, 0x1800, 0x2800, 0x2800, 0x4800, 0x7C00, 0x0800, 0x0800, 0x0000, 0x0000, // 4
+0x7C00, 0x4000, 0x4000, 0x7800, 0x0400, 0x0400, 0x4400, 0x3800, 0x0000, 0x0000, // 5
+0x3800, 0x4400, 0x4000, 0x7800, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // 6
+0x7C00, 0x0400, 0x0800, 0x1000, 0x1000, 0x2000, 0x2000, 0x2000, 0x0000, 0x0000, // 7
+0x3800, 0x4400, 0x4400, 0x3800, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // 8
+0x3800, 0x4400, 0x4400, 0x4400, 0x3C00, 0x0400, 0x4400, 0x3800, 0x0000, 0x0000, // 9
+0x0000, 0x0000, 0x1000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x0000, // :
+0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x0000, 0x0000, 0x1000, 0x1000, 0x1000, // ;
+0x0000, 0x0000, 0x0C00, 0x3000, 0x4000, 0x3000, 0x0C00, 0x0000, 0x0000, 0x0000, // <
+0x0000, 0x0000, 0x0000, 0x7C00, 0x0000, 0x7C00, 0x0000, 0x0000, 0x0000, 0x0000, // =
+0x0000, 0x0000, 0x6000, 0x1800, 0x0400, 0x1800, 0x6000, 0x0000, 0x0000, 0x0000, // >
+0x3800, 0x4400, 0x0400, 0x0800, 0x1000, 0x1000, 0x0000, 0x1000, 0x0000, 0x0000, // ?
+0x3800, 0x4400, 0x4C00, 0x5400, 0x5C00, 0x4000, 0x4000, 0x3800, 0x0000, 0x0000, // @
+0x1000, 0x2800, 0x2800, 0x2800, 0x2800, 0x7C00, 0x4400, 0x4400, 0x0000, 0x0000, // A
+0x7800, 0x4400, 0x4400, 0x7800, 0x4400, 0x4400, 0x4400, 0x7800, 0x0000, 0x0000, // B
+0x3800, 0x4400, 0x4000, 0x4000, 0x4000, 0x4000, 0x4400, 0x3800, 0x0000, 0x0000, // C
+0x7000, 0x4800, 0x4400, 0x4400, 0x4400, 0x4400, 0x4800, 0x7000, 0x0000, 0x0000, // D
+0x7C00, 0x4000, 0x4000, 0x7C00, 0x4000, 0x4000, 0x4000, 0x7C00, 0x0000, 0x0000, // E
+0x7C00, 0x4000, 0x4000, 0x7800, 0x4000, 0x4000, 0x4000, 0x4000, 0x0000, 0x0000, // F
+0x3800, 0x4400, 0x4000, 0x4000, 0x5C00, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // G
+0x4400, 0x4400, 0x4400, 0x7C00, 0x4400, 0x4400, 0x4400, 0x4400, 0x0000, 0x0000, // H
+0x3800, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x3800, 0x0000, 0x0000, // I
+0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x4400, 0x3800, 0x0000, 0x0000, // J
+0x4400, 0x4800, 0x5000, 0x6000, 0x5000, 0x4800, 0x4800, 0x4400, 0x0000, 0x0000, // K
+0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x7C00, 0x0000, 0x0000, // L
+0x4400, 0x6C00, 0x6C00, 0x5400, 0x4400, 0x4400, 0x4400, 0x4400, 0x0000, 0x0000, // M
+0x4400, 0x6400, 0x6400, 0x5400, 0x5400, 0x4C00, 0x4C00, 0x4400, 0x0000, 0x0000, // N
+0x3800, 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // O
+0x7800, 0x4400, 0x4400, 0x4400, 0x7800, 0x4000, 0x4000, 0x4000, 0x0000, 0x0000, // P
+0x3800, 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x5400, 0x3800, 0x0400, 0x0000, // Q
+0x7800, 0x4400, 0x4400, 0x4400, 0x7800, 0x4800, 0x4800, 0x4400, 0x0000, 0x0000, // R
+0x3800, 0x4400, 0x4000, 0x3000, 0x0800, 0x0400, 0x4400, 0x3800, 0x0000, 0x0000, // S
+0x7C00, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // T
+0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // U
+0x4400, 0x4400, 0x4400, 0x2800, 0x2800, 0x2800, 0x1000, 0x1000, 0x0000, 0x0000, // V
+0x4400, 0x4400, 0x5400, 0x5400, 0x5400, 0x6C00, 0x2800, 0x2800, 0x0000, 0x0000, // W
+0x4400, 0x2800, 0x2800, 0x1000, 0x1000, 0x2800, 0x2800, 0x4400, 0x0000, 0x0000, // X
+0x4400, 0x4400, 0x2800, 0x2800, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // Y
+0x7C00, 0x0400, 0x0800, 0x1000, 0x1000, 0x2000, 0x4000, 0x7C00, 0x0000, 0x0000, // Z
+0x1800, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1800, // [
+0x2000, 0x2000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0800, 0x0800, 0x0000, 0x0000, /* \ */
+0x3000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x3000, // ]
+0x1000, 0x2800, 0x2800, 0x4400, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ^
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFE00, // _
+0x2000, 0x1000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // `
+0x0000, 0x0000, 0x3800, 0x4400, 0x3C00, 0x4400, 0x4C00, 0x3400, 0x0000, 0x0000, // a
+0x4000, 0x4000, 0x5800, 0x6400, 0x4400, 0x4400, 0x6400, 0x5800, 0x0000, 0x0000, // b
+0x0000, 0x0000, 0x3800, 0x4400, 0x4000, 0x4000, 0x4400, 0x3800, 0x0000, 0x0000, // c
+0x0400, 0x0400, 0x3400, 0x4C00, 0x4400, 0x4400, 0x4C00, 0x3400, 0x0000, 0x0000, // d
+0x0000, 0x0000, 0x3800, 0x4400, 0x7C00, 0x4000, 0x4400, 0x3800, 0x0000, 0x0000, // e
+0x0C00, 0x1000, 0x7C00, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // f
+0x0000, 0x0000, 0x3400, 0x4C00, 0x4400, 0x4400, 0x4C00, 0x3400, 0x0400, 0x7800, // g
+0x4000, 0x4000, 0x5800, 0x6400, 0x4400, 0x4400, 0x4400, 0x4400, 0x0000, 0x0000, // h
+0x1000, 0x0000, 0x7000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // i
+0x1000, 0x0000, 0x7000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0xE000, // j
+0x4000, 0x4000, 0x4800, 0x5000, 0x6000, 0x5000, 0x4800, 0x4400, 0x0000, 0x0000, // k
+0x7000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // l
+0x0000, 0x0000, 0x7800, 0x5400, 0x5400, 0x5400, 0x5400, 0x5400, 0x0000, 0x0000, // m
+0x0000, 0x0000, 0x5800, 0x6400, 0x4400, 0x4400, 0x4400, 0x4400, 0x0000, 0x0000, // n
+0x0000, 0x0000, 0x3800, 0x4400, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // o
+0x0000, 0x0000, 0x5800, 0x6400, 0x4400, 0x4400, 0x6400, 0x5800, 0x4000, 0x4000, // p
+0x0000, 0x0000, 0x3400, 0x4C00, 0x4400, 0x4400, 0x4C00, 0x3400, 0x0400, 0x0400, // q
+0x0000, 0x0000, 0x5800, 0x6400, 0x4000, 0x4000, 0x4000, 0x4000, 0x0000, 0x0000, // r
+0x0000, 0x0000, 0x3800, 0x4400, 0x3000, 0x0800, 0x4400, 0x3800, 0x0000, 0x0000, // s
+0x2000, 0x2000, 0x7800, 0x2000, 0x2000, 0x2000, 0x2000, 0x1800, 0x0000, 0x0000, // t
+0x0000, 0x0000, 0x4400, 0x4400, 0x4400, 0x4400, 0x4C00, 0x3400, 0x0000, 0x0000, // u
+0x0000, 0x0000, 0x4400, 0x4400, 0x2800, 0x2800, 0x2800, 0x1000, 0x0000, 0x0000, // v
+0x0000, 0x0000, 0x5400, 0x5400, 0x5400, 0x6C00, 0x2800, 0x2800, 0x0000, 0x0000, // w
+0x0000, 0x0000, 0x4400, 0x2800, 0x1000, 0x1000, 0x2800, 0x4400, 0x0000, 0x0000, // x
+0x0000, 0x0000, 0x4400, 0x4400, 0x2800, 0x2800, 0x1000, 0x1000, 0x1000, 0x6000, // y
+0x0000, 0x0000, 0x7C00, 0x0800, 0x1000, 0x2000, 0x4000, 0x7C00, 0x0000, 0x0000, // z
+0x1800, 0x1000, 0x1000, 0x1000, 0x2000, 0x2000, 0x1000, 0x1000, 0x1000, 0x1800, // {
+0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, // |
+0x3000, 0x1000, 0x1000, 0x1000, 0x0800, 0x0800, 0x1000, 0x1000, 0x1000, 0x3000, // }
+0x0000, 0x0000, 0x0000, 0x7400, 0x4C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ~
+};
+
+const uint16_t Font11x18 [] = {
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // sp
+0x0000, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // !
+0x0000, 0x1B00, 0x1B00, 0x1B00, 0x1B00, 0x1B00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // "
+0x0000, 0x1980, 0x1980, 0x1980, 0x1980, 0x7FC0, 0x7FC0, 0x1980, 0x3300, 0x7FC0, 0x7FC0, 0x3300, 0x3300, 0x3300, 0x3300, 0x0000, 0x0000, 0x0000, // #
+0x0000, 0x1E00, 0x3F00, 0x7580, 0x6580, 0x7400, 0x3C00, 0x1E00, 0x0700, 0x0580, 0x6580, 0x6580, 0x7580, 0x3F00, 0x1E00, 0x0400, 0x0400, 0x0000, // $
+0x0000, 0x7000, 0xD800, 0xD840, 0xD8C0, 0xD980, 0x7300, 0x0600, 0x0C00, 0x1B80, 0x36C0, 0x66C0, 0x46C0, 0x06C0, 0x0380, 0x0000, 0x0000, 0x0000, // %
+0x0000, 0x1E00, 0x3F00, 0x3300, 0x3300, 0x3300, 0x1E00, 0x0C00, 0x3CC0, 0x66C0, 0x6380, 0x6180, 0x6380, 0x3EC0, 0x1C80, 0x0000, 0x0000, 0x0000, // &
+0x0000, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // '
+0x0080, 0x0100, 0x0300, 0x0600, 0x0600, 0x0400, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0400, 0x0600, 0x0600, 0x0300, 0x0100, 0x0080, // (
+0x2000, 0x1000, 0x1800, 0x0C00, 0x0C00, 0x0400, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0400, 0x0C00, 0x0C00, 0x1800, 0x1000, 0x2000, // )
+0x0000, 0x0C00, 0x2D00, 0x3F00, 0x1E00, 0x3300, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // *
+0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0xFFC0, 0xFFC0, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // +
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0400, 0x0400, 0x0800, // ,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E00, 0x1E00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // -
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // .
+0x0000, 0x0300, 0x0300, 0x0300, 0x0600, 0x0600, 0x0600, 0x0600, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x1800, 0x1800, 0x1800, 0x0000, 0x0000, 0x0000, // /
+0x0000, 0x1E00, 0x3F00, 0x3300, 0x6180, 0x6180, 0x6180, 0x6D80, 0x6D80, 0x6180, 0x6180, 0x6180, 0x3300, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 0
+0x0000, 0x0600, 0x0E00, 0x1E00, 0x3600, 0x2600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, // 1
+0x0000, 0x1E00, 0x3F00, 0x7380, 0x6180, 0x6180, 0x0180, 0x0300, 0x0600, 0x0C00, 0x1800, 0x3000, 0x6000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x0000, // 2
+0x0000, 0x1C00, 0x3E00, 0x6300, 0x6300, 0x0300, 0x0E00, 0x0E00, 0x0300, 0x0180, 0x0180, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 3
+0x0000, 0x0600, 0x0E00, 0x0E00, 0x1E00, 0x1E00, 0x1600, 0x3600, 0x3600, 0x6600, 0x7F80, 0x7F80, 0x0600, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, // 4
+0x0000, 0x7F00, 0x7F00, 0x6000, 0x6000, 0x6000, 0x6E00, 0x7F00, 0x6380, 0x0180, 0x0180, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 5
+0x0000, 0x1E00, 0x3F00, 0x3380, 0x6180, 0x6000, 0x6E00, 0x7F00, 0x7380, 0x6180, 0x6180, 0x6180, 0x3380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 6
+0x0000, 0x7F80, 0x7F80, 0x0180, 0x0300, 0x0300, 0x0600, 0x0600, 0x0C00, 0x0C00, 0x0C00, 0x0800, 0x1800, 0x1800, 0x1800, 0x0000, 0x0000, 0x0000, // 7
+0x0000, 0x1E00, 0x3F00, 0x6380, 0x6180, 0x6180, 0x2100, 0x1E00, 0x3F00, 0x6180, 0x6180, 0x6180, 0x6180, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 8
+0x0000, 0x1E00, 0x3F00, 0x7300, 0x6180, 0x6180, 0x6180, 0x7380, 0x3F80, 0x1D80, 0x0180, 0x6180, 0x7300, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 9
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // :
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0400, 0x0400, 0x0800, // ;
+0x0000, 0x0000, 0x0000, 0x0000, 0x0080, 0x0380, 0x0E00, 0x3800, 0x6000, 0x3800, 0x0E00, 0x0380, 0x0080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // <
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // =
+0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x7000, 0x1C00, 0x0700, 0x0180, 0x0700, 0x1C00, 0x7000, 0x4000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // >
+0x0000, 0x1F00, 0x3F80, 0x71C0, 0x60C0, 0x00C0, 0x01C0, 0x0380, 0x0700, 0x0E00, 0x0C00, 0x0C00, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // ?
+0x0000, 0x1E00, 0x3F00, 0x3180, 0x7180, 0x6380, 0x6F80, 0x6D80, 0x6D80, 0x6F80, 0x6780, 0x6000, 0x3200, 0x3E00, 0x1C00, 0x0000, 0x0000, 0x0000, // @
+0x0000, 0x0E00, 0x0E00, 0x1B00, 0x1B00, 0x1B00, 0x1B00, 0x3180, 0x3180, 0x3F80, 0x3F80, 0x3180, 0x60C0, 0x60C0, 0x60C0, 0x0000, 0x0000, 0x0000, // A
+0x0000, 0x7C00, 0x7E00, 0x6300, 0x6300, 0x6300, 0x6300, 0x7E00, 0x7E00, 0x6300, 0x6180, 0x6180, 0x6380, 0x7F00, 0x7E00, 0x0000, 0x0000, 0x0000, // B
+0x0000, 0x1E00, 0x3F00, 0x3180, 0x6180, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6180, 0x3180, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // C
+0x0000, 0x7C00, 0x7F00, 0x6300, 0x6380, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6300, 0x6300, 0x7E00, 0x7C00, 0x0000, 0x0000, 0x0000, // D
+0x0000, 0x7F80, 0x7F80, 0x6000, 0x6000, 0x6000, 0x6000, 0x7F00, 0x7F00, 0x6000, 0x6000, 0x6000, 0x6000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x0000, // E
+0x0000, 0x7F80, 0x7F80, 0x6000, 0x6000, 0x6000, 0x6000, 0x7F00, 0x7F00, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x0000, 0x0000, 0x0000, // F
+0x0000, 0x1E00, 0x3F00, 0x3180, 0x6180, 0x6000, 0x6000, 0x6000, 0x6380, 0x6380, 0x6180, 0x6180, 0x3180, 0x3F80, 0x1E00, 0x0000, 0x0000, 0x0000, // G
+0x0000, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x7F80, 0x7F80, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x0000, 0x0000, 0x0000, // H
+0x0000, 0x3F00, 0x3F00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x3F00, 0x3F00, 0x0000, 0x0000, 0x0000, // I
+0x0000, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x6180, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // J
+0x0000, 0x60C0, 0x6180, 0x6300, 0x6600, 0x6600, 0x6C00, 0x7800, 0x7C00, 0x6600, 0x6600, 0x6300, 0x6180, 0x6180, 0x60C0, 0x0000, 0x0000, 0x0000, // K
+0x0000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x0000, // L
+0x0000, 0x71C0, 0x71C0, 0x7BC0, 0x7AC0, 0x6AC0, 0x6AC0, 0x6EC0, 0x64C0, 0x60C0, 0x60C0, 0x60C0, 0x60C0, 0x60C0, 0x60C0, 0x0000, 0x0000, 0x0000, // M
+0x0000, 0x7180, 0x7180, 0x7980, 0x7980, 0x7980, 0x6D80, 0x6D80, 0x6D80, 0x6580, 0x6780, 0x6780, 0x6780, 0x6380, 0x6380, 0x0000, 0x0000, 0x0000, // N
+0x0000, 0x1E00, 0x3F00, 0x3300, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x3300, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // O
+0x0000, 0x7E00, 0x7F00, 0x6380, 0x6180, 0x6180, 0x6180, 0x6380, 0x7F00, 0x7E00, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x0000, 0x0000, 0x0000, // P
+0x0000, 0x1E00, 0x3F00, 0x3300, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6580, 0x6780, 0x3300, 0x3F80, 0x1E40, 0x0000, 0x0000, 0x0000, // Q
+0x0000, 0x7E00, 0x7F00, 0x6380, 0x6180, 0x6180, 0x6380, 0x7F00, 0x7E00, 0x6600, 0x6300, 0x6300, 0x6180, 0x6180, 0x60C0, 0x0000, 0x0000, 0x0000, // R
+0x0000, 0x0E00, 0x1F00, 0x3180, 0x3180, 0x3000, 0x3800, 0x1E00, 0x0700, 0x0380, 0x6180, 0x6180, 0x3180, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // S
+0x0000, 0xFFC0, 0xFFC0, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // T
+0x0000, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // U
+0x0000, 0x60C0, 0x60C0, 0x60C0, 0x3180, 0x3180, 0x3180, 0x1B00, 0x1B00, 0x1B00, 0x1B00, 0x0E00, 0x0E00, 0x0E00, 0x0400, 0x0000, 0x0000, 0x0000, // V
+0x0000, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xCCC0, 0x4C80, 0x4C80, 0x5E80, 0x5280, 0x5280, 0x7380, 0x6180, 0x6180, 0x0000, 0x0000, 0x0000, // W
+0x0000, 0xC0C0, 0x6080, 0x6180, 0x3300, 0x3B00, 0x1E00, 0x0C00, 0x0C00, 0x1E00, 0x1F00, 0x3B00, 0x7180, 0x6180, 0xC0C0, 0x0000, 0x0000, 0x0000, // X
+0x0000, 0xC0C0, 0x6180, 0x6180, 0x3300, 0x3300, 0x1E00, 0x1E00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // Y
+0x0000, 0x3F80, 0x3F80, 0x0180, 0x0300, 0x0300, 0x0600, 0x0C00, 0x0C00, 0x1800, 0x1800, 0x3000, 0x6000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x0000, // Z
+0x0F00, 0x0F00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0F00, 0x0F00, // [
+0x0000, 0x1800, 0x1800, 0x1800, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0300, 0x0300, 0x0300, 0x0000, 0x0000, 0x0000, /* \ */
+0x1E00, 0x1E00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x1E00, 0x1E00, // ]
+0x0000, 0x0C00, 0x0C00, 0x1E00, 0x1200, 0x3300, 0x3300, 0x6180, 0x6180, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ^
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFFE0, 0x0000, // _
+0x0000, 0x3800, 0x1800, 0x0C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // `
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F00, 0x3F80, 0x6180, 0x0180, 0x1F80, 0x3F80, 0x6180, 0x6380, 0x7F80, 0x38C0, 0x0000, 0x0000, 0x0000, // a
+0x0000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6E00, 0x7F00, 0x7380, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x7F00, 0x6E00, 0x0000, 0x0000, 0x0000, // b
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E00, 0x3F00, 0x7380, 0x6180, 0x6000, 0x6000, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // c
+0x0000, 0x0180, 0x0180, 0x0180, 0x0180, 0x1D80, 0x3F80, 0x7380, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x3F80, 0x1D80, 0x0000, 0x0000, 0x0000, // d
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E00, 0x3F00, 0x7300, 0x6180, 0x7F80, 0x7F80, 0x6000, 0x7180, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // e
+0x0000, 0x07C0, 0x0FC0, 0x0C00, 0x0C00, 0x7F80, 0x7F80, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // f
+0x0000, 0x0000, 0x0000, 0x0000, 0x1D80, 0x3F80, 0x7380, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x3F80, 0x1D80, 0x0180, 0x6380, 0x7F00, 0x3E00, // g
+0x0000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6F00, 0x7F80, 0x7180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x0000, 0x0000, 0x0000, // h
+0x0000, 0x0600, 0x0600, 0x0000, 0x0000, 0x3E00, 0x3E00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, // i
+0x0600, 0x0600, 0x0000, 0x0000, 0x3E00, 0x3E00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x4600, 0x7E00, 0x3C00, // j
+0x0000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6180, 0x6300, 0x6600, 0x6C00, 0x7C00, 0x7600, 0x6300, 0x6300, 0x6180, 0x60C0, 0x0000, 0x0000, 0x0000, // k
+0x0000, 0x3E00, 0x3E00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, // l
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xDD80, 0xFFC0, 0xCEC0, 0xCCC0, 0xCCC0, 0xCCC0, 0xCCC0, 0xCCC0, 0xCCC0, 0xCCC0, 0x0000, 0x0000, 0x0000, // m
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6F00, 0x7F80, 0x7180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x0000, 0x0000, 0x0000, // n
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E00, 0x3F00, 0x7380, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // o
+0x0000, 0x0000, 0x0000, 0x0000, 0x6E00, 0x7F00, 0x7380, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x7F00, 0x6E00, 0x6000, 0x6000, 0x6000, 0x6000, // p
+0x0000, 0x0000, 0x0000, 0x0000, 0x1D80, 0x3F80, 0x7380, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x3F80, 0x1D80, 0x0180, 0x0180, 0x0180, 0x0180, // q
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6700, 0x3F80, 0x3900, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x0000, 0x0000, // r
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E00, 0x3F80, 0x6180, 0x6000, 0x7F00, 0x3F80, 0x0180, 0x6180, 0x7F00, 0x1E00, 0x0000, 0x0000, 0x0000, // s
+0x0000, 0x0000, 0x0800, 0x1800, 0x1800, 0x7F00, 0x7F00, 0x1800, 0x1800, 0x1800, 0x1800, 0x1800, 0x1800, 0x1F80, 0x0F80, 0x0000, 0x0000, 0x0000, // t
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6380, 0x7F80, 0x3D80, 0x0000, 0x0000, 0x0000, // u
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x60C0, 0x3180, 0x3180, 0x3180, 0x1B00, 0x1B00, 0x1B00, 0x0E00, 0x0E00, 0x0600, 0x0000, 0x0000, 0x0000, // v
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xDD80, 0xDD80, 0xDD80, 0x5500, 0x5500, 0x5500, 0x7700, 0x7700, 0x2200, 0x2200, 0x0000, 0x0000, 0x0000, // w
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6180, 0x3300, 0x3300, 0x1E00, 0x0C00, 0x0C00, 0x1E00, 0x3300, 0x3300, 0x6180, 0x0000, 0x0000, 0x0000, // x
+0x0000, 0x0000, 0x0000, 0x0000, 0x6180, 0x6180, 0x3180, 0x3300, 0x3300, 0x1B00, 0x1B00, 0x1B00, 0x0E00, 0x0E00, 0x0E00, 0x1C00, 0x7C00, 0x7000, // y
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7FC0, 0x7FC0, 0x0180, 0x0300, 0x0600, 0x0C00, 0x1800, 0x3000, 0x7FC0, 0x7FC0, 0x0000, 0x0000, 0x0000, // z
+0x0380, 0x0780, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0E00, 0x1C00, 0x1C00, 0x0E00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0780, 0x0380, // {
+0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, // |
+0x3800, 0x3C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0E00, 0x0700, 0x0700, 0x0E00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x3C00, 0x3800, // }
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3880, 0x7F80, 0x4700, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ~
+};
+
+const uint16_t Font16x26 [] = {
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [ ]
+0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03C0,0x03C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [!]
+0x1E3C,0x1E3C,0x1E3C,0x1E3C,0x1E3C,0x1E3C,0x1E3C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = ["]
+0x01CE,0x03CE,0x03DE,0x039E,0x039C,0x079C,0x3FFF,0x7FFF,0x0738,0x0F38,0x0F78,0x0F78,0x0E78,0xFFFF,0xFFFF,0x1EF0,0x1CF0,0x1CE0,0x3CE0,0x3DE0,0x39E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [#]
+0x03FC,0x0FFE,0x1FEE,0x1EE0,0x1EE0,0x1EE0,0x1EE0,0x1FE0,0x0FE0,0x07E0,0x03F0,0x01FC,0x01FE,0x01FE,0x01FE,0x01FE,0x01FE,0x01FE,0x3DFE,0x3FFC,0x0FF0,0x01E0,0x01E0,0x0000,0x0000,0x0000, // Ascii = [$]
+0x3E03,0xF707,0xE78F,0xE78E,0xE39E,0xE3BC,0xE7B8,0xE7F8,0xF7F0,0x3FE0,0x01C0,0x03FF,0x07FF,0x07F3,0x0FF3,0x1EF3,0x3CF3,0x38F3,0x78F3,0xF07F,0xE03F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [%]
+0x07E0,0x0FF8,0x0F78,0x1F78,0x1F78,0x1F78,0x0F78,0x0FF0,0x0FE0,0x1F80,0x7FC3,0xFBC3,0xF3E7,0xF1F7,0xF0F7,0xF0FF,0xF07F,0xF83E,0x7C7F,0x3FFF,0x1FEF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [&]
+0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03C0,0x01C0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [']
+0x003F,0x007C,0x01F0,0x01E0,0x03C0,0x07C0,0x0780,0x0780,0x0F80,0x0F00,0x0F00,0x0F00,0x0F00,0x0F00,0x0F00,0x0F80,0x0780,0x0780,0x07C0,0x03C0,0x01E0,0x01F0,0x007C,0x003F,0x000F,0x0000, // Ascii = [(]
+0x7E00,0x1F00,0x07C0,0x03C0,0x01E0,0x01F0,0x00F0,0x00F0,0x00F8,0x0078,0x0078,0x0078,0x0078,0x0078,0x0078,0x00F8,0x00F0,0x00F0,0x01F0,0x01E0,0x03C0,0x07C0,0x1F00,0x7E00,0x7800,0x0000, // Ascii = [)]
+0x03E0,0x03C0,0x01C0,0x39CE,0x3FFF,0x3F7F,0x0320,0x0370,0x07F8,0x0F78,0x1F3C,0x0638,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [*]
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0xFFFF,0xFFFF,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [+]
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x03E0,0x01E0,0x01E0,0x01E0,0x01C0,0x0380, // Ascii = [,]
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3FFE,0x3FFE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [-]
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [.]
+0x000F,0x000F,0x001E,0x001E,0x003C,0x003C,0x0078,0x0078,0x00F0,0x00F0,0x01E0,0x01E0,0x03C0,0x03C0,0x0780,0x0780,0x0F00,0x0F00,0x1E00,0x1E00,0x3C00,0x3C00,0x7800,0x7800,0xF000,0x0000, // Ascii = [/]
+0x07F0,0x0FF8,0x1F7C,0x3E3E,0x3C1E,0x7C1F,0x7C1F,0x780F,0x780F,0x780F,0x780F,0x780F,0x780F,0x780F,0x7C1F,0x7C1F,0x3C1E,0x3E3E,0x1F7C,0x0FF8,0x07F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [0]
+0x00F0,0x07F0,0x3FF0,0x3FF0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x3FFF,0x3FFF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [1]
+0x0FE0,0x3FF8,0x3C7C,0x003C,0x003E,0x003E,0x003E,0x003C,0x003C,0x007C,0x00F8,0x01F0,0x03E0,0x07C0,0x0780,0x0F00,0x1E00,0x3E00,0x3C00,0x3FFE,0x3FFE,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [2]
+0x0FF0,0x1FF8,0x1C7C,0x003E,0x003E,0x003E,0x003C,0x003C,0x00F8,0x0FF0,0x0FF8,0x007C,0x003E,0x001E,0x001E,0x001E,0x001E,0x003E,0x1C7C,0x1FF8,0x1FE0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [3]
+0x0078,0x00F8,0x00F8,0x01F8,0x03F8,0x07F8,0x07F8,0x0F78,0x1E78,0x1E78,0x3C78,0x7878,0x7878,0xFFFF,0xFFFF,0x0078,0x0078,0x0078,0x0078,0x0078,0x0078,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [4]
+0x1FFC,0x1FFC,0x1FFC,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x1FE0,0x1FF8,0x00FC,0x007C,0x003E,0x003E,0x001E,0x003E,0x003E,0x003C,0x1C7C,0x1FF8,0x1FE0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [5]
+0x01FC,0x07FE,0x0F8E,0x1F00,0x1E00,0x3E00,0x3C00,0x3C00,0x3DF8,0x3FFC,0x7F3E,0x7E1F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3E0F,0x1E1F,0x1F3E,0x0FFC,0x03F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [6]
+0x3FFF,0x3FFF,0x3FFF,0x000F,0x001E,0x001E,0x003C,0x0038,0x0078,0x00F0,0x00F0,0x01E0,0x01E0,0x03C0,0x03C0,0x0780,0x0F80,0x0F80,0x0F00,0x1F00,0x1F00,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [7]
+0x07F8,0x0FFC,0x1F3E,0x1E1E,0x3E1E,0x3E1E,0x1E1E,0x1F3C,0x0FF8,0x07F0,0x0FF8,0x1EFC,0x3E3E,0x3C1F,0x7C1F,0x7C0F,0x7C0F,0x3C1F,0x3F3E,0x1FFC,0x07F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [8]
+0x07F0,0x0FF8,0x1E7C,0x3C3E,0x3C1E,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x3C1F,0x3E3F,0x1FFF,0x07EF,0x001F,0x001E,0x001E,0x003E,0x003C,0x38F8,0x3FF0,0x1FE0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [9]
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [:]
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x03E0,0x01E0,0x01E0,0x01E0,0x03C0,0x0380, // Ascii = [;]
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0003,0x000F,0x003F,0x00FC,0x03F0,0x0FC0,0x3F00,0xFE00,0x3F00,0x0FC0,0x03F0,0x00FC,0x003F,0x000F,0x0003,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [<]
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xFFFF,0xFFFF,0x0000,0x0000,0x0000,0xFFFF,0xFFFF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [=]
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xE000,0xF800,0x7E00,0x1F80,0x07E0,0x01F8,0x007E,0x001F,0x007E,0x01F8,0x07E0,0x1F80,0x7E00,0xF800,0xE000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [>]
+0x1FF0,0x3FFC,0x383E,0x381F,0x381F,0x001E,0x001E,0x003C,0x0078,0x00F0,0x01E0,0x03C0,0x03C0,0x07C0,0x07C0,0x0000,0x0000,0x0000,0x07C0,0x07C0,0x07C0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [?]
+0x03F8,0x0FFE,0x1F1E,0x3E0F,0x3C7F,0x78FF,0x79EF,0x73C7,0xF3C7,0xF38F,0xF38F,0xF38F,0xF39F,0xF39F,0x73FF,0x7BFF,0x79F7,0x3C00,0x1F1C,0x0FFC,0x03F8,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [@]
+0x0000,0x0000,0x0000,0x03E0,0x03E0,0x07F0,0x07F0,0x07F0,0x0F78,0x0F78,0x0E7C,0x1E3C,0x1E3C,0x3C3E,0x3FFE,0x3FFF,0x781F,0x780F,0xF00F,0xF007,0xF007,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [A]
+0x0000,0x0000,0x0000,0x3FF8,0x3FFC,0x3C3E,0x3C1E,0x3C1E,0x3C1E,0x3C3E,0x3C7C,0x3FF0,0x3FF8,0x3C7E,0x3C1F,0x3C1F,0x3C0F,0x3C0F,0x3C1F,0x3FFE,0x3FF8,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [B]
+0x0000,0x0000,0x0000,0x01FF,0x07FF,0x1F87,0x3E00,0x3C00,0x7C00,0x7800,0x7800,0x7800,0x7800,0x7800,0x7C00,0x7C00,0x3E00,0x3F00,0x1F83,0x07FF,0x01FF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [C]
+0x0000,0x0000,0x0000,0x7FF0,0x7FFC,0x787E,0x781F,0x781F,0x780F,0x780F,0x780F,0x780F,0x780F,0x780F,0x780F,0x780F,0x781F,0x781E,0x787E,0x7FF8,0x7FE0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [D]
+0x0000,0x0000,0x0000,0x3FFF,0x3FFF,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3FFE,0x3FFE,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3FFF,0x3FFF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [E]
+0x0000,0x0000,0x0000,0x1FFF,0x1FFF,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x1FFF,0x1FFF,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [F]
+0x0000,0x0000,0x0000,0x03FE,0x0FFF,0x1F87,0x3E00,0x7C00,0x7C00,0x7800,0xF800,0xF800,0xF87F,0xF87F,0x780F,0x7C0F,0x7C0F,0x3E0F,0x1F8F,0x0FFF,0x03FE,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [G]
+0x0000,0x0000,0x0000,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7FFF,0x7FFF,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [H]
+0x0000,0x0000,0x0000,0x3FFF,0x3FFF,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x3FFF,0x3FFF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [I]
+0x0000,0x0000,0x0000,0x1FFC,0x1FFC,0x007C,0x007C,0x007C,0x007C,0x007C,0x007C,0x007C,0x007C,0x007C,0x007C,0x007C,0x0078,0x0078,0x38F8,0x3FF0,0x3FC0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [J]
+0x0000,0x0000,0x0000,0x3C1F,0x3C1E,0x3C3C,0x3C78,0x3CF0,0x3DE0,0x3FE0,0x3FC0,0x3F80,0x3FC0,0x3FE0,0x3DF0,0x3CF0,0x3C78,0x3C7C,0x3C3E,0x3C1F,0x3C0F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [K]
+0x0000,0x0000,0x0000,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3FFF,0x3FFF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [L]
+0x0000,0x0000,0x0000,0xF81F,0xFC1F,0xFC1F,0xFE3F,0xFE3F,0xFE3F,0xFF7F,0xFF77,0xFF77,0xF7F7,0xF7E7,0xF3E7,0xF3E7,0xF3C7,0xF007,0xF007,0xF007,0xF007,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [M]
+0x0000,0x0000,0x0000,0x7C0F,0x7C0F,0x7E0F,0x7F0F,0x7F0F,0x7F8F,0x7F8F,0x7FCF,0x7BEF,0x79EF,0x79FF,0x78FF,0x78FF,0x787F,0x783F,0x783F,0x781F,0x781F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [N]
+0x0000,0x0000,0x0000,0x07F0,0x1FFC,0x3E3E,0x7C1F,0x780F,0x780F,0xF80F,0xF80F,0xF80F,0xF80F,0xF80F,0xF80F,0x780F,0x780F,0x7C1F,0x3E3E,0x1FFC,0x07F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [O]
+0x0000,0x0000,0x0000,0x3FFC,0x3FFF,0x3E1F,0x3E0F,0x3E0F,0x3E0F,0x3E0F,0x3E1F,0x3E3F,0x3FFC,0x3FF0,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [P]
+0x0000,0x0000,0x0000,0x07F0,0x1FFC,0x3E3E,0x7C1F,0x780F,0x780F,0xF80F,0xF80F,0xF80F,0xF80F,0xF80F,0xF80F,0x780F,0x780F,0x7C1F,0x3E3E,0x1FFC,0x07F8,0x007C,0x003F,0x000F,0x0003,0x0000, // Ascii = [Q]
+0x0000,0x0000,0x0000,0x3FF0,0x3FFC,0x3C7E,0x3C3E,0x3C1E,0x3C1E,0x3C3E,0x3C3C,0x3CFC,0x3FF0,0x3FE0,0x3DF0,0x3CF8,0x3C7C,0x3C3E,0x3C1E,0x3C1F,0x3C0F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [R]
+0x0000,0x0000,0x0000,0x07FC,0x1FFE,0x3E0E,0x3C00,0x3C00,0x3C00,0x3E00,0x1FC0,0x0FF8,0x03FE,0x007F,0x001F,0x000F,0x000F,0x201F,0x3C3E,0x3FFC,0x1FF0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [S]
+0x0000,0x0000,0x0000,0xFFFF,0xFFFF,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [T]
+0x0000,0x0000,0x0000,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x3C1E,0x3C1E,0x3E3E,0x1FFC,0x07F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [U]
+0x0000,0x0000,0x0000,0xF007,0xF007,0xF807,0x780F,0x7C0F,0x3C1E,0x3C1E,0x3E1E,0x1E3C,0x1F3C,0x1F78,0x0F78,0x0FF8,0x07F0,0x07F0,0x07F0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [V]
+0x0000,0x0000,0x0000,0xE003,0xF003,0xF003,0xF007,0xF3E7,0xF3E7,0xF3E7,0x73E7,0x7BF7,0x7FF7,0x7FFF,0x7F7F,0x7F7F,0x7F7E,0x3F7E,0x3E3E,0x3E3E,0x3E3E,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [W]
+0x0000,0x0000,0x0000,0xF807,0x7C0F,0x3E1E,0x3E3E,0x1F3C,0x0FF8,0x07F0,0x07E0,0x03E0,0x03E0,0x07F0,0x0FF8,0x0F7C,0x1E7C,0x3C3E,0x781F,0x780F,0xF00F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [X]
+0x0000,0x0000,0x0000,0xF807,0x7807,0x7C0F,0x3C1E,0x3E1E,0x1F3C,0x0F78,0x0FF8,0x07F0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [Y]
+0x0000,0x0000,0x0000,0x7FFF,0x7FFF,0x000F,0x001F,0x003E,0x007C,0x00F8,0x00F0,0x01E0,0x03E0,0x07C0,0x0F80,0x0F00,0x1E00,0x3E00,0x7C00,0x7FFF,0x7FFF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [Z]
+0x07FF,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x07FF,0x07FF,0x0000, // Ascii = [[]
+0x7800,0x7800,0x3C00,0x3C00,0x1E00,0x1E00,0x0F00,0x0F00,0x0780,0x0780,0x03C0,0x03C0,0x01E0,0x01E0,0x00F0,0x00F0,0x0078,0x0078,0x003C,0x003C,0x001E,0x001E,0x000F,0x000F,0x0007,0x0000, // Ascii = [\]
+0x7FF0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x7FF0,0x7FF0,0x0000, // Ascii = []]
+0x00C0,0x01C0,0x01C0,0x03E0,0x03E0,0x07F0,0x07F0,0x0778,0x0F78,0x0F38,0x1E3C,0x1E3C,0x3C1E,0x3C1E,0x380F,0x780F,0x7807,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [^]
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xFFFF,0xFFFF,0x0000,0x0000,0x0000, // Ascii = [_]
+0x00F0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [`]
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0FF8,0x3FFC,0x3C7C,0x003E,0x003E,0x003E,0x07FE,0x1FFE,0x3E3E,0x7C3E,0x783E,0x7C3E,0x7C7E,0x3FFF,0x1FCF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [a]
+0x3C00,0x3C00,0x3C00,0x3C00,0x3C00,0x3C00,0x3DF8,0x3FFE,0x3F3E,0x3E1F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3C1F,0x3C1E,0x3F3E,0x3FFC,0x3BF0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [b]
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03FE,0x0FFF,0x1F87,0x3E00,0x3E00,0x3C00,0x7C00,0x7C00,0x7C00,0x3C00,0x3E00,0x3E00,0x1F87,0x0FFF,0x03FE,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [c]
+0x001F,0x001F,0x001F,0x001F,0x001F,0x001F,0x07FF,0x1FFF,0x3E3F,0x3C1F,0x7C1F,0x7C1F,0x7C1F,0x781F,0x781F,0x7C1F,0x7C1F,0x3C3F,0x3E7F,0x1FFF,0x0FDF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [d]
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03F8,0x0FFC,0x1F3E,0x3E1E,0x3C1F,0x7C1F,0x7FFF,0x7FFF,0x7C00,0x7C00,0x3C00,0x3E00,0x1F07,0x0FFF,0x03FE,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [e]
+0x01FF,0x03E1,0x03C0,0x07C0,0x07C0,0x07C0,0x7FFF,0x7FFF,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [f]
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x07EF,0x1FFF,0x3E7F,0x3C1F,0x7C1F,0x7C1F,0x781F,0x781F,0x781F,0x7C1F,0x7C1F,0x3C3F,0x3E7F,0x1FFF,0x0FDF,0x001E,0x001E,0x001E,0x387C,0x3FF8, // Ascii = [g]
+0x3C00,0x3C00,0x3C00,0x3C00,0x3C00,0x3C00,0x3DFC,0x3FFE,0x3F9E,0x3F1F,0x3E1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [h]
+0x01F0,0x01F0,0x0000,0x0000,0x0000,0x0000,0x7FE0,0x7FE0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [i]
+0x00F8,0x00F8,0x0000,0x0000,0x0000,0x0000,0x3FF8,0x3FF8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F0,0x71F0,0x7FE0, // Ascii = [j]
+0x3C00,0x3C00,0x3C00,0x3C00,0x3C00,0x3C00,0x3C1F,0x3C3E,0x3C7C,0x3CF8,0x3DF0,0x3DE0,0x3FC0,0x3FC0,0x3FE0,0x3DF0,0x3CF8,0x3C7C,0x3C3E,0x3C1F,0x3C1F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [k]
+0x7FF0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [l]
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xF79E,0xFFFF,0xFFFF,0xFFFF,0xFBE7,0xF9E7,0xF1C7,0xF1C7,0xF1C7,0xF1C7,0xF1C7,0xF1C7,0xF1C7,0xF1C7,0xF1C7,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [m]
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3DFC,0x3FFE,0x3F9E,0x3F1F,0x3E1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [n]
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x07F0,0x1FFC,0x3E3E,0x3C1F,0x7C1F,0x780F,0x780F,0x780F,0x780F,0x780F,0x7C1F,0x3C1F,0x3E3E,0x1FFC,0x07F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [o]
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3DF8,0x3FFE,0x3F3E,0x3E1F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3C1F,0x3E1E,0x3F3E,0x3FFC,0x3FF8,0x3C00,0x3C00,0x3C00,0x3C00,0x3C00, // Ascii = [p]
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x07EE,0x1FFE,0x3E7E,0x3C1E,0x7C1E,0x781E,0x781E,0x781E,0x781E,0x781E,0x7C1E,0x7C3E,0x3E7E,0x1FFE,0x0FDE,0x001E,0x001E,0x001E,0x001E,0x001E, // Ascii = [q]
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x1F7F,0x1FFF,0x1FE7,0x1FC7,0x1F87,0x1F00,0x1F00,0x1F00,0x1F00,0x1F00,0x1F00,0x1F00,0x1F00,0x1F00,0x1F00,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [r]
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x07FC,0x1FFE,0x1E0E,0x3E00,0x3E00,0x3F00,0x1FE0,0x07FC,0x00FE,0x003E,0x001E,0x001E,0x3C3E,0x3FFC,0x1FF0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [s]
+0x0000,0x0000,0x0000,0x0780,0x0780,0x0780,0x7FFF,0x7FFF,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x07C0,0x03FF,0x01FF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [t]
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C3E,0x3C7E,0x3EFE,0x1FFE,0x0FDE,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [u]
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xF007,0x780F,0x780F,0x3C1E,0x3C1E,0x3E1E,0x1E3C,0x1E3C,0x0F78,0x0F78,0x0FF0,0x07F0,0x07F0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [v]
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xF003,0xF1E3,0xF3E3,0xF3E7,0xF3F7,0xF3F7,0x7FF7,0x7F77,0x7F7F,0x7F7F,0x7F7F,0x3E3E,0x3E3E,0x3E3E,0x3E3E,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [w]
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x7C0F,0x3E1E,0x3E3C,0x1F3C,0x0FF8,0x07F0,0x07F0,0x03E0,0x07F0,0x07F8,0x0FF8,0x1E7C,0x3E3E,0x3C1F,0x781F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [x]
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xF807,0x780F,0x7C0F,0x3C1E,0x3C1E,0x1E3C,0x1E3C,0x1F3C,0x0F78,0x0FF8,0x07F0,0x07F0,0x03E0,0x03E0,0x03C0,0x03C0,0x03C0,0x0780,0x0F80,0x7F00, // Ascii = [y]
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3FFF,0x3FFF,0x001F,0x003E,0x007C,0x00F8,0x01F0,0x03E0,0x07C0,0x0F80,0x1F00,0x1E00,0x3C00,0x7FFF,0x7FFF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [z]
+0x01FE,0x03E0,0x03C0,0x03C0,0x03C0,0x03C0,0x01E0,0x01E0,0x01E0,0x01C0,0x03C0,0x3F80,0x3F80,0x03C0,0x01C0,0x01E0,0x01E0,0x01E0,0x03C0,0x03C0,0x03C0,0x03C0,0x03E0,0x01FE,0x007E,0x0000, // Ascii = [{]
+0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x0000, // Ascii = [|]
+0x3FC0,0x03E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01C0,0x03C0,0x03C0,0x01C0,0x01E0,0x00FE,0x00FE,0x01E0,0x01C0,0x03C0,0x03C0,0x01C0,0x01E0,0x01E0,0x01E0,0x01E0,0x03E0,0x3FC0,0x3F00,0x0000, // Ascii = [}]
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3F07,0x7FC7,0x73E7,0xF1FF,0xF07E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [~]
+};
+
+
+FontDef_t Font_7x10 = {
+ 7,
+ 10,
+ Font7x10
+};
+
+FontDef_t Font_11x18 = {
+ 11,
+ 18,
+ Font11x18
+};
+
+FontDef_t Font_16x26 = {
+ 16,
+ 26,
+ Font16x26
+};
+
+char* FONTS_GetStringSize(char* str, FONTS_SIZE_t* SizeStruct, FontDef_t* Font) {
+ /* Fill settings */
+ SizeStruct->Height = Font->FontHeight;
+ SizeStruct->Length = Font->FontWidth * strlen(str);
+
+ /* Return pointer */
+ return str;
+}
diff --git a/RTLGDB/Project/SSD1306/fonts.h b/RTLGDB/Project/SSD1306/fonts.h
new file mode 100644
index 0000000..bbd25f9
--- /dev/null
+++ b/RTLGDB/Project/SSD1306/fonts.h
@@ -0,0 +1,132 @@
+/**
+ * original author: Tilen Majerle
+ * modification for STM32f10x: Alexander Lutsai
+
+ ----------------------------------------------------------------------
+ Copyright (C) Alexander Lutsai, 2016
+ Copyright (C) Tilen Majerle, 2015
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ ----------------------------------------------------------------------
+ */
+#ifndef FONTS_H
+#define FONTS_H 120
+
+/* C++ detection */
+#ifdef __cplusplus
+extern C {
+#endif
+
+/**
+ *
+ * Default fonts library. It is used in all LCD based libraries.
+ *
+ * \par Supported fonts
+ *
+ * Currently, these fonts are supported:
+ * - 7 x 10 pixels
+ * - 11 x 18 pixels
+ * - 16 x 26 pixels
+
+ */
+#include "device.h"
+#include "string.h"
+
+/**
+ * @defgroup LIB_Typedefs
+ * @brief Library Typedefs
+ * @{
+ */
+
+/**
+ * @brief Font structure used on my LCD libraries
+ */
+typedef struct {
+ uint8_t FontWidth; /*!< Font width in pixels */
+ uint8_t FontHeight; /*!< Font height in pixels */
+ const uint16_t *data; /*!< Pointer to data font data array */
+} FontDef_t;
+
+/**
+ * @brief String length and height
+ */
+typedef struct {
+ uint16_t Length; /*!< String length in units of pixels */
+ uint16_t Height; /*!< String height in units of pixels */
+} FONTS_SIZE_t;
+
+/**
+ * @}
+ */
+
+/**
+ * @defgroup FONTS_FontVariables
+ * @brief Library font variables
+ * @{
+ */
+
+/**
+ * @brief 7 x 10 pixels font size structure
+ */
+extern FontDef_t Font_7x10;
+
+/**
+ * @brief 11 x 18 pixels font size structure
+ */
+extern FontDef_t Font_11x18;
+
+/**
+ * @brief 16 x 26 pixels font size structure
+ */
+extern FontDef_t Font_16x26;
+
+/**
+ * @}
+ */
+
+/**
+ * @defgroup FONTS_Functions
+ * @brief Library functions
+ * @{
+ */
+
+/**
+ * @brief Calculates string length and height in units of pixels depending on string and font used
+ * @param *str: String to be checked for length and height
+ * @param *SizeStruct: Pointer to empty @ref FONTS_SIZE_t structure where informations will be saved
+ * @param *Font: Pointer to @ref FontDef_t font used for calculations
+ * @retval Pointer to string used for length and height
+ */
+char* FONTS_GetStringSize(char* str, FONTS_SIZE_t* SizeStruct, FontDef_t* Font);
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* C++ detection */
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
+
diff --git a/RTLGDB/Project/WS2812/WS2812.c b/RTLGDB/Project/WS2812/WS2812.c
new file mode 100644
index 0000000..c5d93ef
--- /dev/null
+++ b/RTLGDB/Project/WS2812/WS2812.c
@@ -0,0 +1,354 @@
+#include "WS2812.h"
+
+/* Quick and dirty, we use one big DMA buffer for the whole strip length.
+ * TODO: use smaller DMA buffer and fill in bit patterns on the fly */
+uint8_t dma_buffer[WS2812_DMABUF_LEN(WS2812_LEDS_MAX)];
+
+/* scale uint8 value from range 2-255 to range 0-scale */
+static inline uint8_t WS2812_Scale(uint8_t value, uint8_t scale)
+{
+ uint32_t tmp;
+
+ tmp = value * scale;
+ tmp /= 256;
+
+ return (uint8_t)tmp;
+}
+
+// wake up waiting tasks when DMA transfer is complete
+static void master_tr_done_callback(void *pdata, SpiIrq event)
+{
+ BaseType_t task_woken, result;
+ WS2812_t *cfg;
+
+ task_woken = pdFALSE;
+ cfg = (WS2812_t *) pdata;
+
+ switch (event)
+ {
+ case SpiRxIrq:
+ break;
+
+ case SpiTxIrq:
+ result = xEventGroupSetBitsFromISR(cfg->events, BIT_DONE, &task_woken);
+ if(result == pdPASS)
+ {
+ portYIELD_FROM_ISR(task_woken);
+ }
+ break;
+
+ default:
+ DBG_8195A("WS2812: Unknown SPI irq event!\n");
+ }
+}
+
+static void WS2812_HSV2RGB(WS2812_HSV_t *hsv, WS2812_RGB_t *rgb)
+{
+ //uint8_t r, g, b;
+ uint8_t hue, sat, val;
+ uint8_t base, sector, offset;
+ uint8_t rise, fall;
+
+ // scale hue to range 0- 3*64. Makes subsequent calculations easier
+ hue = WS2812_Scale(hsv->HUE, 192);
+ sat = hsv->Sat;
+ val = hsv->Value;
+
+ sector = hue / 64;
+ offset = hue % 64;
+
+ // get common white base level and remaining colour amplitude
+ base = 255 - sat;
+
+ rise = (offset * sat * 4) / 256;
+ fall = 255 - base - rise;
+
+ rise = (rise * val) / 256;
+ fall = (fall * val) / 256;
+ base = (base * val) / 256;
+
+ rgb->R = base;
+ rgb->G = base;
+ rgb->B = base;
+
+ switch (sector)
+ {
+ case 0:
+ rgb->R += fall;
+ rgb->G += rise;
+ break;
+ case 1:
+ rgb->G += fall;
+ rgb->B += rise;
+ break;
+ case 2:
+ rgb->R += rise;
+ rgb->B += fall;
+ break;
+ }
+}
+
+// convert a RGB byte into SPI data stream with 2 bits per byte
+static uint8_t *WS2812_RGB2PWM(uint8_t *dst, const uint8_t colour)
+{
+ uint32_t cnt, data = colour;
+
+ for (cnt = 0; cnt < 4; ++cnt)
+ {
+ switch (data & 0xC0)
+ {
+ case 0x00:
+ *dst = WS2812_BITS_00;
+ break;
+ case 0x40:
+ *dst = WS2812_BITS_01;
+ break;
+ case 0x80:
+ *dst = WS2812_BITS_10;
+ break;
+ case 0xC0:
+ *dst = WS2812_BITS_11;
+ break;
+ }
+ dst++;
+ data <<= 2;
+ }
+ return dst;
+}
+
+static int32_t WS2812_TX(WS2812_t *cfg, uint16_t delay)
+{
+ int32_t result;
+ EventBits_t rcvd_events;
+ TickType_t timeout;
+ BaseType_t status;
+
+ // wait for any SPI transfer to finish
+ while(cfg->spi_master.state & SPI_STATE_TX_BUSY)
+ {
+ vTaskDelay(0);
+ }
+
+ result = 0;
+
+ // obey requested delay
+ if(delay > 0)
+ {
+ vTaskDelay(delay);
+ }
+
+ // lock the DMA buffer mutex while it is transferred
+ status = xSemaphoreTake(cfg->mutex, configTICK_RATE_HZ);
+ if(status != pdTRUE)
+ {
+ printf("WS2812: [%s] Timeout waiting for config mutex.\n", __func__);
+ result = -1;
+ goto err_out;
+ }
+
+ if(cfg->dma_buff == NULL || cfg->buff_len == 0)
+ {
+ printf("WS2812: [%s] DMA buffer invalid\n", __func__);
+ result = -1;
+ goto err_out;
+ }
+
+ xEventGroupClearBits(cfg->events, BIT_DONE);
+ spi_master_write_stream_dma(&cfg->spi_master, (char *)(cfg->dma_buff[0]), cfg->buff_len);
+
+ timeout = 1000 / portTICK_PERIOD_MS;
+ rcvd_events = xEventGroupWaitBits(
+ cfg->events,
+ BIT_DONE, // wait for DMA TX done
+ pdTRUE, // clear event bit
+ pdFALSE, // do not wait for all bits to be set
+ timeout );
+
+ if(!(rcvd_events & BIT_DONE))
+ {
+ printf("WS2812: [%s] DMA timeout\n", __func__);
+ result = -1;
+ goto err_out;
+ }
+
+err_out:
+ xSemaphoreGive(cfg->mutex);
+
+ return result;
+}
+
+int32_t WS2812_Update(WS2812_t *cfg, WS2812_HSV_t hsv_values[], uint32_t strip_len, uint16_t delay)
+{
+ uint32_t i;
+ uint8_t *bufp;
+ uint16_t len;
+ BaseType_t status;
+ int32_t result;
+ WS2812_RGB_t rgb;
+
+ // make sure DMA buffer is not in use
+ while(cfg->spi_master.state & SPI_STATE_TX_BUSY)
+ {
+ vTaskDelay(0);
+ }
+
+ // lock the DMA buffer mutex while we fill it
+ status = xSemaphoreTake(cfg->mutex, configTICK_RATE_HZ);
+ if(status != pdTRUE)
+ {
+ printf("WS2812: [%s] Timeout waiting for config mutex.\n", __func__);
+ result = -1;
+ goto err_out;
+ }
+
+ bufp = &(cfg->dma_buff[0]);
+
+ // make sure that we do not exceed the buffer
+ len = min(strip_len, cfg->strip_len);
+
+ // copy pixel data into DMA buffer
+ for(i = 0; i < len; ++i) // ++i ??
+ {
+ WS2812_HSV2RGB(&hsv_values[i], &rgb);
+ bufp = WS2812_RGB2PWM(bufp, rgb.G);
+ bufp = WS2812_RGB2PWM(bufp, rgb.R);
+ bufp = WS2812_RGB2PWM(bufp, rgb.B);
+ }
+
+ /* turn unused pixels at end of strip off */
+ if(cfg->strip_len > len)
+ {
+ memset(bufp, WS2812_BITS_00, cfg->strip_len - len);
+ bufp += cfg->strip_len - len;
+ }
+
+ /* add reset pulse */
+ memset(bufp, 0x0, WS2812_RESET_LEN);
+
+ /* release buffer mutex */
+ xSemaphoreGive(cfg->mutex);
+
+ /* send it off to the strip */
+ result = WS2812_TX(cfg, delay);
+
+err_out:
+ return result;
+}
+
+WS2812_t *WS2812_Init(uint16_t strip_len)
+{
+ int32_t result;
+ WS2812_t *cfg;
+
+ result = 0;
+
+ cfg = malloc(sizeof(*cfg));
+ if(cfg == NULL)
+ {
+ printf("WS2812: [%s] malloc for cfg failed\n", __func__);
+ result = -1;
+ goto err_out;
+ }
+
+ memset(cfg, 0x0, sizeof(*cfg));
+
+ cfg->mutex = xSemaphoreCreateMutex();
+ if(cfg->mutex == NULL)
+ {
+ printf("WS2812: [%s] Mutex creation failed\n", __func__);
+ result = -1;
+ goto err_out;
+ }
+
+ cfg->events = xEventGroupCreate();
+ if(cfg->events == NULL)
+ {
+ printf("WS2812: [%s] Creating event group failed\n", __func__);
+ result = -1;
+ goto err_out;
+ }
+
+ spi_init(&(cfg->spi_master), WS2812_SPI_MOSI, WS2812_SPI_MISO, WS2812_SPI_SCLK, WS2812_SPI_CS);
+ spi_format(&(cfg->spi_master), 8, 3, 0);
+ spi_frequency(&(cfg->spi_master), WS2812_SPI_FREQ);
+ spi_irq_hook(&(cfg->spi_master), master_tr_done_callback, (uint32_t)cfg);
+
+ result = WS2812_SetLen(cfg, strip_len);
+ if(result != 0)
+ {
+ printf("WS2812: [%s] ws2812_set_len() failed\n", __func__);
+ }
+
+err_out:
+ if(result != 0 && cfg != NULL)
+ {
+ if(cfg->mutex != NULL)
+ {
+ vQueueDelete(cfg->mutex);
+ }
+
+ if(cfg->events != NULL)
+ {
+ vEventGroupDelete(cfg->events);
+ }
+
+ if(cfg->dma_buff != NULL)
+ {
+ free(cfg->dma_buff);
+ }
+
+ free(cfg);
+ cfg = NULL;
+ }
+
+ return cfg;
+}
+
+int32_t WS2812_SetLen(WS2812_t *cfg, uint16_t strip_len)
+{
+ int32_t result;
+ BaseType_t status;
+ uint32_t reset_off;
+
+ result = 0;
+
+ if(cfg == NULL)
+ {
+ printf("WS2812: [%s] no config given\n", __func__);
+ result = -1;
+ goto err_out;
+ }
+
+ /* lock the config mutex */
+ status = xSemaphoreTake(cfg->mutex, configTICK_RATE_HZ);
+ if(status != pdTRUE)
+ {
+ printf("WS2812: [%s] Timeout waiting for config mutex.\n", __func__);
+ result = -1;
+ goto err_out;
+ }
+
+ if(strip_len <= WS2812_LEDS_MAX)
+ {
+ /* TODO: use dynamically allocated buffer */
+ cfg->dma_buff = dma_buffer;
+
+ /* initialise LEDs to off and add reset pulse at end of strip */
+ reset_off = WS2812_DMABUF_LEN(strip_len) - WS2812_RESET_LEN;
+ memset(&(cfg->dma_buff[0]), WS2812_BITS_00, reset_off);
+ memset(&(cfg->dma_buff[reset_off]), 0x0, WS2812_RESET_LEN);
+ cfg->strip_len = strip_len;
+ cfg->buff_len = WS2812_DMABUF_LEN(strip_len);
+ }
+ else
+ {
+ printf("WS2812: [%s] Strip too long for DMA buffer\n", __func__);
+ result = -1;
+ }
+
+ xSemaphoreGive(cfg->mutex);
+
+err_out:
+ return result;
+}
+
diff --git a/RTLGDB/Project/WS2812/WS2812.h b/RTLGDB/Project/WS2812/WS2812.h
new file mode 100644
index 0000000..d9970e3
--- /dev/null
+++ b/RTLGDB/Project/WS2812/WS2812.h
@@ -0,0 +1,69 @@
+#ifndef _WS2812_H_
+#define _WS2812_H_
+
+#include "FreeRTOS.h"
+#include "task.h"
+#include "event_groups.h"
+#include
+#include
+#include
+#include
+#include "semphr.h"
+#include "event_groups.h"
+
+
+#define WS2812_LEDS_MAX 500
+#define WS2812_RESET_LEN (50 / 2)
+#define WS2812_DMABUF_LEN(x) ((x) * 3 * 4 + WS2812_RESET_LEN)
+
+#define WS2812_SPI_FREQ 3200000 // и делённое на 4 (4 бита SPI за 1 бит WS8212) = в итоге 800кГц
+#define WS2812_SPI_MOSI PC_2 // SPI0
+#define WS2812_SPI_MISO NC//PC_3
+#define WS2812_SPI_SCLK NC//PC_1
+#define WS2812_SPI_CS NC//PC_0
+
+// Events to signal completion of DMA transfer
+#define BIT_START (1 << 0)
+#define BIT_DONE (1 << 1)
+
+// посылается 2 бита протокола WS2812 за один байт SPI, один бит WS2812 за 4 бита SPI.
+#define WS2812_BITS_00 0x88
+#define WS2812_BITS_01 0x8e
+#define WS2812_BITS_10 0xe8
+#define WS2812_BITS_11 0xee
+
+typedef struct
+{
+ uint8_t R;
+ uint8_t G;
+ uint8_t B;
+} WS2812_RGB_t;
+
+typedef struct
+{
+ uint8_t HUE;
+ uint8_t Sat;
+ uint8_t Value;
+} WS2812_HSV_t;
+
+typedef struct
+{
+ spi_t spi_master;
+ EventGroupHandle_t *events;
+ SemaphoreHandle_t *mutex;
+ uint8_t *dma_buff;
+ size_t buff_len;
+ uint16_t strip_len;
+} WS2812_t;
+
+WS2812_t *WS2812_Init(uint16_t len);
+int32_t WS2812_SetLen(WS2812_t *cfg, uint16_t len);
+int32_t WS2812_DeInit(WS2812_t *cfg);
+int32_t WS2812_Update(WS2812_t *cfg, WS2812_HSV_t hsv[], uint32_t len, uint16_t delay);
+
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#define max(a,b) ((a) > (b) ? (a) : (b))
+#define scale_up(x) ((x) << 8)
+#define scale_down(x) ((x) >> 8)
+
+#endif // _WS2812_H_
diff --git a/RTLGDB/Project/adc_ws/adc_ws.c b/RTLGDB/Project/adc_ws/adc_ws.c
new file mode 100644
index 0000000..725dfef
--- /dev/null
+++ b/RTLGDB/Project/adc_ws/adc_ws.c
@@ -0,0 +1,234 @@
+/*
+ * ADC + Websocket
+ *
+ * Created on: 18 РёСЋРЅ. 2017 Рі.
+ * Author: pvvx
+ */
+
+#include
+
+#include "rtl8195a.h"
+#include "device.h"
+#include "PinNames.h"
+
+#include "basic_types.h"
+#include "diag.h"
+#include "osdep_api.h"
+
+#include "FreeRTOS.h"
+#include "diag.h"
+
+//------------------------------------------------------------------------------
+#include "objects.h"
+#include "PinNames.h"
+#include "hal_adc.h"
+#include "analogin_api.h"
+#include "timer_api.h"
+
+#include "web_srv.h"
+#include "websock.h"
+#include "web_websocket.h"
+#include "driver/adc_drv.h"
+#include "rtl8195a/rtl_libc.h"
+
+
+//------------------------------------------------------------------------------
+//#define ADC_USE_TIMER TIMER3 // если назначено, то для чтения ADC используется таймер
+ // иначе ADC int
+//------------------------------------------------------------------------------
+
+
+#ifndef CONFIG_MBED_ENABLED
+extern void *pvPortZalloc(size_t xWantedSize);
+extern void vPortFree(void *pv);
+extern void *pvPortMalloc(size_t xWantedSize);
+#undef malloc
+#define malloc pvPortMalloc
+#undef zalloc
+#define zalloc pvPortZalloc
+#undef free
+#define free vPortFree
+#endif
+
+//------------------------------------------------------------------------------
+typedef union _adc_data
+{
+ unsigned short us;
+} ADC_DATA, *PADC_DATA;
+
+typedef struct _adc_drv
+{
+ signed char init; // флаг
+ unsigned char tmp;
+
+ unsigned short count; // счетчик считанных значений
+ unsigned short overrun; // счет переполнений буфера
+
+ unsigned short buf_idx; // объем буфера pbuf[buf_idx+1], максимальный индекс-номер замера
+ unsigned short buf_rx; // индекс-номер ещё не считанного замера
+ unsigned short buf_tx; // индекс-номер для записи следующего замера
+ PADC_DATA pbuf;
+#ifdef ADC_USE_TIMER
+ gtimer_t timer;
+#endif
+} ADC_DRV, *PADC_DRV;
+
+//#define mMIN(a, b) ((ab)?a:b)
+
+ADC_DRV adc_drv =
+{
+ .buf_idx = (1460*2 - 80)/(sizeof(ADC_DATA)/2) // циклический буфер на ~1420 замеров (см. sizeof(ADC_DATA))
+ // Если шаг заполнения 1 ms -> буфер на 1.4 сек
+ // Оптимизация под TCP: (TCP_MSS*2 - 80)/2 = (1460*2 - 80)/2 = 1420
+};
+
+void adc_int_handler(void *par)
+{
+ PADC_DRV p = par; // &adc_drv
+ if(p->pbuf)
+ {
+#ifndef ADC_USE_TIMER
+ int i = 4;
+ while(i--)
+#endif
+ {
+ PADC_DATA pd = p->pbuf + p->buf_tx;
+ pd->us = HAL_ADC_READ32(REG_ADC_FIFO_READ); // 2 -> sample -> 24.4 kHz (if ADC irq!)
+// (void)HAL_ADC_READ32(REG_ADC_FIFO_READ); // 4 sample -> 12.2 kHz (if ADC irq!)
+// (void)HAL_ADC_READ32(REG_ADC_FIFO_READ); // 6 sample -> 8.133 kHz (if ADC irq!)
+// (void)HAL_ADC_READ32(REG_ADC_FIFO_READ); // 8 sample -> 6.1 kHz (if ADC irq!)
+
+ if(p->buf_tx >= p->buf_idx) p->buf_tx = 0;
+ else p->buf_tx++;
+ if(p->buf_rx == p->buf_tx)
+ {
+ p->overrun++; // todo: if(p->overrun++ > 100000) deinit() ?
+ if(p->buf_rx >= p->buf_idx) p->buf_rx = 0;
+ else p->buf_rx++;
+ };
+ }
+ // Clear ADC Status
+ (void)HAL_ADC_READ32(REG_ADC_INTR_STS);
+ };
+}
+
+size_t adc_getdata(void *pd, uint16 cnt)
+{
+ PADC_DRV p = &adc_drv;
+ if(p->init <= 0) return 0;
+ unsigned short *pus = (unsigned short *) pd;
+ taskDISABLE_INTERRUPTS();
+ uint16 buf_rx = p->buf_rx;
+ *pus++ = cnt; // кол-во замеров
+ *pus++ = p->count + p->overrun; // индекс замера для анализа пропусков на стороне приемника
+ // если не пропущено, то равен прошлому + кол-во считанных замеров в прошлом блоке
+ p->count += cnt; // p->overrun = 0;
+ unsigned char *puc = (unsigned char *) pus;
+ if(cnt)
+ {
+ uint16 lend = buf_rx + cnt;
+ if(lend > p->buf_idx)
+ {
+ lend -= p->buf_idx + 1;
+ p->buf_rx = lend;
+ }
+ else
+ {
+ p->buf_rx = lend;
+ lend = 0;
+ };
+ size_t len = (cnt - lend) *sizeof(ADC_DATA);
+ if(len) memcpy(puc, (void *)(p->pbuf + buf_rx), len);
+ if(lend) memcpy(puc + len, (void *)p->pbuf, lend *sizeof(ADC_DATA));
+ }
+ taskENABLE_INTERRUPTS();
+ return cnt * sizeof(ADC_DATA) + 4;
+}
+
+uint16 adc_chkdata(uint16 cnt)
+{
+ PADC_DRV p = &adc_drv;
+ if(p->init <= 0) return 0;
+ int len = p->buf_tx - p->buf_rx;
+ if(len < 0) len += p->buf_idx + 1;
+ if(cnt > (uint16)len) cnt = (uint16)len;
+ return cnt;
+}
+
+int adc_ws(TCP_SERV_CONN *ts_conn, char cmd)
+{
+ PADC_DRV p = &adc_drv;
+ switch(cmd)
+ {
+ case 'd': // deinit
+ if(p->init > 0)
+ {
+#ifdef ADC_USE_TIMER
+ gtimer_stop(&p->timer);
+ gtimer_deinit(&p->timer);
+ ADCDisable();
+#else
+ ADCDisable();
+ ADCIrqDeInit();
+#endif
+ ADCDeInit();
+ if(p->pbuf)
+ {
+ free(p->pbuf);
+ p->pbuf = NULL;
+ }
+ p->init = -1;
+ return 0;
+ }
+ return 1;
+ case 'c': // get count
+ return adc_chkdata(p->buf_idx + 1);
+ case 'i': // init
+ return p->init;
+ default: // get_data
+ if(p->init <= 0)
+ {
+ p->count = 0;
+ p->overrun = 0;
+// p->errs = 0;
+ if(!p->pbuf)
+ {
+ p->pbuf = zalloc((p->buf_idx + 1) * sizeof(ADC_DATA));
+ if(!p->pbuf)
+ {
+ error_printf("Error create buffer!\n");
+ return -1;
+ };
+ p->buf_tx = 0;
+ p->buf_rx = 0;
+ };
+ ADCInit(ADC2_SEL);
+#ifdef ADC_USE_TIMER
+ // Initial a periodical timer
+ gtimer_init(&p->timer, ADC_USE_TIMER);
+ gtimer_start_periodical(&p->timer, 1000, (void*)adc_int_handler, (uint32_t)p);
+ rtl_printf("ADC Timer Period = %u us\n", &p->timer.hal_gtimer_adp.TimerLoadValueUs);
+#else
+ ADCIrqInit(adc_int_handler,(uint32)p, BIT_ADC_FIFO_FULL_EN); // BIT_ADC_FIFO_RD_REQ_EN ?
+#endif
+ ADCEnable();
+ p->init = 1;
+// return 0;
+ }
+ case 'g': // get
+ {
+ uint32 i = adc_chkdata(p->buf_idx + 1);
+ if (i)
+ {
+ WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
+ i = mMIN((web_conn->msgbufsize / sizeof(ADC_DATA)), i);
+ if (websock_tx_frame(ts_conn, WS_OPCODE_BINARY | WS_FRAGMENT_FIN, web_conn->msgbuf, adc_getdata(web_conn->msgbuf, i)) != ERR_OK)
+ return -1;
+ }
+ return i;
+ }
+ }
+ return -1;
+}
+
diff --git a/RTLGDB/Project/build_info.h b/RTLGDB/Project/build_info.h
new file mode 100644
index 0000000..1c37c5c
--- /dev/null
+++ b/RTLGDB/Project/build_info.h
@@ -0,0 +1,7 @@
+#define UTS_VERSION "2017/11/28-22:25:03"
+#define RTL8195AFW_COMPILE_TIME "2017/11/28-22:25:03"
+#define RTL8195AFW_COMPILE_DATE "20171128"
+#define RTL8195AFW_COMPILE_BY "Andrew"
+#define RTL8195AFW_COMPILE_HOST ""
+#define RTL8195AFW_COMPILE_DOMAIN
+#define RTL195AFW_COMPILER "gcc 6.3.1"
diff --git a/RTLGDB/Project/console/adc_tst.c b/RTLGDB/Project/console/adc_tst.c
new file mode 100644
index 0000000..cd20875
--- /dev/null
+++ b/RTLGDB/Project/console/adc_tst.c
@@ -0,0 +1,291 @@
+/*
+ * adc_tst.c
+ *
+ * Created on: 04/04/2017.
+ * Author: pvvx
+ */
+
+#include
+#include "rtl8195a.h"
+#include "FreeRTOS.h"
+#include "rtl8195a/rtl_libc.h"
+
+//------------------------------------------------------------------------------
+#include "objects.h"
+#include "PinNames.h"
+#include "hal_adc.h"
+#include "analogin_api.h"
+#include "strproc.h"
+//------------------------------------------------------------------------------
+analogin_t adc;
+
+static void fATADI(int argc, char *argv[])
+{
+ int count = 8;
+ int channel = 2;
+ union
+ {
+ unsigned int ui[2];
+ unsigned short us[4];
+ } x;
+
+ uint16_t adcdat;
+ memset(&adc, 0, sizeof(adc));
+
+
+ // ConfigDebugErr |= (_DBG_ADC_|_DBG_GDMA_);
+ // ConfigDebugInfo |= (_DBG_ADC_|_DBG_GDMA_);
+
+ if (argc > 1)
+ {
+ channel = atoi(argv[1]);
+ channel &= 0x03;
+ if(!channel) channel = 2;
+ }
+
+ if (argc > 2)
+ {
+ count = atoi(argv[2]);
+ }
+
+ analogin_init(&adc, (channel+1) | (PORT_V << 4));
+
+ PSAL_ADC_HND pSalADCHND = &((&(adc.SalADCMngtAdpt))->pSalHndPriv->SalADCHndPriv);
+
+ uint32_t sum = 0;
+ for (uint32_t i = 1; i <= count; i++)
+ {
+ RtkADCReceiveBuf(pSalADCHND, &x.ui);
+ adcdat = x.us[channel];
+ if((i % 8) == 0 || (i == count))
+ {
+ printf("0x%04x\n", adcdat);
+ }
+ else
+ {
+ printf("0x%04x, ", adcdat);
+ }
+ sum += adcdat;
+ }
+ analogin_deinit(&adc);
+ printf("ADC%d = 0x%04x\n", channel, sum / count);
+ // sys_adc_calibration(0, &channel, &count);
+}
+
+static void fATADD(int argc, char *argv[])
+{
+ int count = 64;
+ int channel = 2;
+ uint16_t adcdat;
+ memset(&adc, 0, sizeof(adc));
+
+// ConfigDebugErr |= (_DBG_ADC_|_DBG_GDMA_);
+// ConfigDebugInfo |= (_DBG_ADC_|_DBG_GDMA_);
+
+ if (argc > 1)
+ {
+ channel = atoi(argv[1]);
+ channel &= 0x03;
+ if(!channel) channel = 1;
+ }
+
+ if (argc > 2)
+ {
+ count = atoi(argv[2]);
+ if (count <= 2)
+ {
+ count = 64;
+ }
+ };
+
+ analogin_init(&adc, (channel+1) | (PORT_V << 4));
+ SAL_ADC_TRANSFER_BUF trbuf;
+ trbuf.pDataBuf = zalloc(count*4);
+ if(trbuf.pDataBuf)
+ {
+ trbuf.DataLen = count/2; // x32 bit ?
+ trbuf.RSVD = 0;
+ adc.SalADCHndPriv.SalADCHndPriv.pRXBuf = &trbuf;
+ adc.SalADCHndPriv.SalADCHndPriv.OpType = ADC_DMA_TYPE;
+
+ adc.HalADCInitData.ADCEndian = ADC_DATA_ENDIAN_LITTLE; //ADC endian selection,
+ //but actually it's for 32-bit ADC data swap control
+ //1'b0: no swap,
+ //1'b1: swap the upper 16-bit and the lower 16-bit
+// adc.HalADCInitData.ADCCompOnly = ADC_FEATURE_DISABLED; //ADC compare mode only enable (without FIFO enable)
+// adc.HalADCInitData.ADCEnManul = ADC_FEATURE_ENABLED; // ADC_FEATURE_DISABLED; //ADC enable manually
+// adc.HalADCInitData.ADCIdx = channel+1; //ADC index used (1..3 ?)
+// adc.HalADCInitData.ADCBurstSz = 8; //ADC DMA operation threshold
+// adc.HalADCInitData.ADCOneShotTD = 8; //ADC one shot mode threshold
+// adc.HalADCInitData.ADCDataRate = 0; // 0xff; // ADC down sample data rate ??
+ adc.HalADCInitData.ADCAudioEn = ADC_FEATURE_ENABLED; //ADC audio mode enable // ADC_FEATURE_DISABLED
+// adc.HalADCInitData.ADCOneShotEn = ADC_FEATURE_DISABLED; //ADC one shot mode threshold
+ adc.HalADCInitData.ADCInInput = ADC_FEATURE_ENABLED; //ADC Input is internal?
+// adc.HalADCInitData.ADCEn = ADC_DISABLE; //ADC_ENABLE;
+
+ HalADCInit8195a(&adc.HalADCInitData);
+ /* Read Content */
+ HAL_ADC_READ32(REG_ADC_FIFO_READ);
+ HAL_ADC_READ32(REG_ADC_INTR_STS);
+ RtkADCReceive(&adc.SalADCHndPriv.SalADCHndPriv);
+ while(adc.SalADCHndPriv.SalADCHndPriv.DevSts != ADC_STS_IDLE);
+ uint16 * ptr = (uint16 *) trbuf.pDataBuf;
+ // RtkADCDMAInit(&adc.SalADCHndPriv.SalADCHndPriv);
+ for (uint32_t i = 1; i <= count; i++)
+ {
+ if((i % 16) == 0 || (i == count))
+ {
+ printf("%04x\n", *ptr);
+ }
+ else
+ {
+ printf("%04x ", *ptr);
+ }
+ ptr++;
+ }
+ uint32_t sum = 0;
+ ptr = (uint16 *) trbuf.pDataBuf;
+ for (uint32_t i = 1; i <= count; i++)
+ {
+ printf("%d\n", *ptr);
+ sum += *ptr;
+ ptr++;
+ if((i%512)==0) vTaskDelay(10);
+ }
+/*
+ printf("OpType:\t\t%p\n", adc.SalADCHndPriv.SalADCHndPriv.OpType);
+ printf("pRXBuf:\t\t%p\n", adc.SalADCHndPriv.SalADCHndPriv.pRXBuf);
+ printf("pDataBuf:\t%p\n", adc.SalADCHndPriv.SalADCHndPriv.pRXBuf->pDataBuf);
+ printf("DataLen:\t%p\n", adc.SalADCHndPriv.SalADCHndPriv.pRXBuf->DataLen);
+ printf("ADCDataRate:\t%p\n", adc.HalADCInitData.ADCDataRate);
+ printf("ADCData:\t%p\n", adc.HalADCInitData.ADCData);
+ printf("ADCIdx:\t\t%p\n", adc.HalADCInitData.ADCIdx);
+ printf("ADCPWCtrl:\t%p\n", adc.HalADCInitData.ADCPWCtrl);
+ printf("ADCAnaParAd3:\t%p\n", adc.HalADCInitData.ADCAnaParAd3);
+ printf("ADC%d = 0x%04x\n", channel, analogin_read_u16(&adc));
+ printf("ADC%d = 0x%04x\n", channel, analogin_read_u16(&adc));
+*/
+ analogin_deinit(&adc);
+ free(trbuf.pDataBuf);
+ printf("ADC%d = 0x%04x\n", channel, sum / count);
+
+ }
+ else
+ {
+ error_printf("%s: malloc failed!\n", __func__);
+ };
+
+// sys_adc_calibration(0, &channel, &count);
+}
+
+static void fATADC(int argc, char *argv[]) {
+
+ int count = 8;
+ int channel = 2;
+ uint16_t adcdat;
+ memset(&adc, 0, sizeof(adc));
+
+
+// ConfigDebugErr |= (_DBG_ADC_|_DBG_GDMA_);
+// ConfigDebugInfo |= (_DBG_ADC_|_DBG_GDMA_);
+
+ if (argc > 1)
+ {
+ channel = atoi(argv[1]);
+ channel &= 0x03;
+ if(!channel) channel = 1;
+ }
+
+ if (argc > 2)
+ {
+ count = atoi(argv[2]);
+ }
+
+ analogin_init(&adc, (channel+1) | (PORT_V << 4));
+
+ uint32_t sum = 0;
+ for (uint32_t i = 1; i <= count; i++)
+ {
+ adcdat = analogin_read_u16(&adc);
+ if((i % 8) == 0 || (i == count))
+ {
+ printf("0x%04x\n", adcdat);
+ }
+ else
+ {
+ printf("0x%04x, ", adcdat);
+ }
+ sum += adcdat;
+ }
+ analogin_deinit(&adc);
+ printf("ADC%d = 0x%04x\n", channel, sum / count);
+// sys_adc_calibration(0, &channel, &count);
+}
+
+static void fATSA(int argc, char *argv[])
+{
+// uint32_t tConfigDebugInfo = ConfigDebugInfo;
+ int channel;
+ char *ptmp;
+ uint16_t offset, gain, adcdat;
+ memset(&adc, 0, sizeof(adc));
+
+ if (argc < 2)
+ {
+ printf("Usage: ATSA=CHANNEL(0~2)\n");
+ printf("Usage: ATSA=k_get\n");
+ printf("Usage: ATSA=k_set[offet(hex),gain(hex)]\n");
+ return;
+ }
+
+ if (strcmp(argv[1], "k_get") == 0)
+ {
+ sys_adc_calibration(0, &offset, &gain);
+// printf("[ATSA] offset = 0x%04X, gain = 0x%04X", offset, gain);
+ }
+ else if (strcmp(argv[1], "k_set") == 0)
+ {
+ if (argc != 4)
+ {
+ printf("Usage: ATSA=k_set[offet(hex),gain(hex)]\n");
+ return;
+ }
+ offset = strtoul(argv[2], &ptmp, 16);
+ gain = strtoul(argv[3], &ptmp, 16);
+ sys_adc_calibration(1, &offset, &gain);
+// printf("[ATSA] offset = 0x%04X, gain = 0x%04X", offset, gain);
+ }
+ else
+ {
+ channel = atoi(argv[1]);
+ if (channel < 0 || channel > 2)
+ {
+ printf("Usage: ATSA=CHANNEL(0~2)\n");
+ return;
+ }
+ // Remove debug info massage
+// ConfigDebugInfo = 0;
+ if (channel == 0)
+ analogin_init(&adc, AD_1);
+ else if (channel == 1)
+ analogin_init(&adc, AD_2);
+ else
+ analogin_init(&adc, AD_3);
+// analogin_read_u16(&adc);
+ adcdat = analogin_read_u16(&adc) >> 4;
+ analogin_deinit(&adc);
+ // Recover debug info massage
+// ConfigDebugInfo = tConfigDebugInfo;
+
+ printf("A%d = 0x%04X\n", channel, adcdat);
+ }
+}
+
+//------------------------------------------------------------------------------
+MON_RAM_TAB_SECTION COMMAND_TABLE console_commands_adc[] =
+{
+ { "ATADC", 0, fATADC, ": ADC Test" },
+ { "ATADD", 0, fATADD, ": ADC DMA Test" },
+ { "ATADI", 0, fATADI, ": ADC Irq Test" },
+ { "ATSA" , 0, fATSA , ": ADC at" }
+};
diff --git a/RTLGDB/Project/console/atcmd_user.c b/RTLGDB/Project/console/atcmd_user.c
new file mode 100644
index 0000000..d9ea6c1
--- /dev/null
+++ b/RTLGDB/Project/console/atcmd_user.c
@@ -0,0 +1,390 @@
+#include
+
+#ifdef CONFIG_AT_USR
+
+#include "FreeRTOS.h"
+#include "task.h"
+#include "semphr.h"
+#include "freertos_pmu.h"
+#include "at_cmd/log_service.h"
+#include "at_cmd/atcmd_wifi.h"
+#include
+#include "tcpip.h"
+#include
+#include
+#include
+#include "tcm_heap.h"
+#include "rtl8195a/rtl_libc.h"
+
+#include "flash_api.h"
+#include "sleep_ex_api.h"
+
+#include "lwip/tcp_impl.h"
+
+extern char str_rom_57ch3Dch0A[]; // "=========================================================\n" 57
+
+#define printf rtl_printf // DiagPrintf
+
+/* RAM/TCM/Heaps info */
+extern void ShowMemInfo(void);
+/*
+void ShowMemInfo(void)
+{
+ printf("\nCLK CPU\t\t%d Hz\nRAM heap\t%d bytes\nTCM heap\t%d bytes\n",
+ HalGetCpuClk(), xPortGetFreeHeapSize(), tcm_heap_freeSpace());
+}
+ */
+//------------------------------------------------------------------------------
+// Mem, Tasks info
+//------------------------------------------------------------------------------
+void fATST(int argc, char *argv[]) {
+ (void) argc;
+ (void) argv;
+ ShowMemInfo();
+#if CONFIG_DEBUG_LOG > 1
+ extern int min_free_heap_size;
+ printf("\nMin free heap size %d bytes\n", min_free_heap_size);
+#endif
+#if 0 //CONFIG_DEBUG_LOG > 1
+ dump_mem_block_list();
+ tcm_heap_dump();
+#endif
+ printf("\n");
+#if (configGENERATE_RUN_TIME_STATS == 1)
+ char *cBuffer = pvPortMalloc(512);
+ if(cBuffer != NULL) {
+ vTaskGetRunTimeStats((char *)cBuffer);
+ printf("%s", cBuffer);
+ }
+ vPortFree(cBuffer);
+#endif
+#if defined(configUSE_TRACE_FACILITY) && (configUSE_TRACE_FACILITY == 1) && (configUSE_STATS_FORMATTING_FUNCTIONS == 1)
+ {
+ char * pcWriteBuffer = malloc(1024);
+ if(pcWriteBuffer) {
+ vTaskList((char*)pcWriteBuffer);
+ printf("\nTask List:\n");
+ printf(&str_rom_57ch3Dch0A[7]); // "==========================================\n"
+ printf("Name\t Status Priority HighWaterMark TaskNumber\n%s\n", pcWriteBuffer);
+ free(pcWriteBuffer);
+ }
+ }
+#endif
+}
+/*-------------------------------------------------------------------------------------
+ Копирует данные из области align(4) (flash, registers, ...) в область align(1) (ram)
+--------------------------------------------------------------------------------------*/
+extern void copy_align4_to_align1(unsigned char * pd, void * ps, unsigned int len);
+/*
+static void copy_align4_to_align1(unsigned char * pd, void * ps, unsigned int len)
+{
+ union {
+ unsigned char uc[4];
+ unsigned int ud;
+ }tmp;
+ unsigned int *p = (unsigned int *)((unsigned int)ps & (~3));
+ unsigned int xlen = (unsigned int)ps & 3;
+ // unsigned int size = len;
+
+ if(xlen) {
+ tmp.ud = *p++;
+ while (len) {
+ len--;
+ *pd++ = tmp.uc[xlen++];
+ if(xlen & 4) break;
+ }
+ }
+ xlen = len >> 2;
+ while(xlen) {
+ tmp.ud = *p++;
+ *pd++ = tmp.uc[0];
+ *pd++ = tmp.uc[1];
+ *pd++ = tmp.uc[2];
+ *pd++ = tmp.uc[3];
+ xlen--;
+ }
+ if(len & 3) {
+ tmp.ud = *p;
+ pd[0] = tmp.uc[0];
+ if(len & 2) {
+ pd[1] = tmp.uc[1];
+ if(len & 1) {
+ pd[2] = tmp.uc[2];
+ }
+ }
+ }
+ // return size;
+}
+*/
+/*
+ * int print_hex_dump(uint8_t *buf, int len, unsigned char k)
+ */
+int print_hex_dump(uint8_t *buf, int len, unsigned char k) {
+ uint32_t ss[2];
+ ss[0] = 0x78323025; // "%02x"
+ ss[1] = k; // ","...'\0'
+ uint8_t * ptr = buf;
+ int result = 0;
+ while (len--) {
+ if (len == 0)
+ ss[1] = 0;
+ result += printf((uint8_t *) &ss, *ptr++);
+ }
+ return result;
+}
+
+extern char str_rom_hex_addr[]; // in *.ld "[Addr] .0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .A .B .C .D .E .F\n"
+void dump_bytes(uint32 addr, int size)
+{
+ uint8 buf[17];
+ int symbs_line = sizeof(buf)-1;
+ printf(str_rom_hex_addr);
+ while (size) {
+ if (symbs_line > size) symbs_line = size;
+ printf("%08X ", addr);
+ copy_align4_to_align1(buf, (void *) addr, symbs_line);
+ print_hex_dump(buf, symbs_line, ' ');
+ int i;
+ for(i = 0 ; i < symbs_line ; i++) {
+ if(buf[i] < 0x20 || buf[i] > 0x7E) {
+ buf[i] = '.';
+ }
+ }
+ buf[symbs_line] = 0;
+ i = (sizeof(buf)-1) - symbs_line;
+ while(i--) printf(" ");
+ printf(" %s\r\n", buf);
+ addr += symbs_line;
+ size -= symbs_line;
+ }
+}
+//------------------------------------------------------------------------------
+// Dump byte register
+//------------------------------------------------------------------------------
+extern uint32_t Strtoul(
+ IN const uint8_t *nptr,
+ IN uint8_t **endptr,
+ IN uint32_t base
+);
+
+static void fATSB(int argc, char *argv[])
+{
+ int size = 16;
+ uint32 addr = Strtoul(argv[1],0,16);
+ if (argc > 2) {
+ size = Strtoul(argv[2],0,10);
+ if (size <= 0 || size > 16384)
+ size = 16;
+ }
+ if(addr + size > SPI_FLASH_BASE) {
+ flash_turnon();
+ dump_bytes(addr, size);
+ SpicDisableRtl8195A();
+ }
+ else {
+ dump_bytes(addr, size);
+ }
+}
+extern uint32_t CmdDumpWord(IN uint16_t argc, IN uint8_t *argv[]);
+extern uint32_t CmdWriteWord(IN uint16_t argc, IN uint8_t *argv[]);
+//------------------------------------------------------------------------------
+// Dump dword register
+//------------------------------------------------------------------------------
+static void fATSD(int argc, char *argv[])
+{
+/*
+ if (argc > 2) {
+ int size = Strtoul(argv[2],0,10);
+ if (size <= 0 || size > 16384)
+ argv[2] = "16";
+ }
+*/
+ CmdDumpWord(argc-1, (unsigned char**)(argv+1));
+}
+//------------------------------------------------------------------------------
+// Write dword register
+//------------------------------------------------------------------------------
+static void fATSW(int argc, char *argv[])
+{
+ CmdWriteWord(argc-1, (unsigned char**)(argv+1));
+}
+
+/* Get one byte from the 4-byte address */
+#define ip4_addr1(ipaddr) (((uint8_t*)(ipaddr))[0])
+#define ip4_addr2(ipaddr) (((uint8_t*)(ipaddr))[1])
+#define ip4_addr3(ipaddr) (((uint8_t*)(ipaddr))[2])
+#define ip4_addr4(ipaddr) (((uint8_t*)(ipaddr))[3])
+/* These are cast to uint16_t, with the intent that they are often arguments
+ * to printf using the U16_F format from cc.h. */
+#define ip4_addr1_16(ipaddr) ((uint16_t)ip4_addr1(ipaddr))
+#define ip4_addr2_16(ipaddr) ((uint16_t)ip4_addr2(ipaddr))
+#define ip4_addr3_16(ipaddr) ((uint16_t)ip4_addr3(ipaddr))
+#define ip4_addr4_16(ipaddr) ((uint16_t)ip4_addr4(ipaddr))
+
+#define IP2STR(ipaddr) ip4_addr1_16(ipaddr), \
+ ip4_addr2_16(ipaddr), \
+ ip4_addr3_16(ipaddr), \
+ ip4_addr4_16(ipaddr)
+
+#define IPSTR "%d.%d.%d.%d"
+
+extern const char * const tcp_state_str[];
+/*
+static const char * const tcp_state_str[] = {
+ "CLOSED",
+ "LISTEN",
+ "SYN_SENT",
+ "SYN_RCVD",
+ "ESTABLISHED",
+ "FIN_WAIT_1",
+ "FIN_WAIT_2",
+ "CLOSE_WAIT",
+ "CLOSING",
+ "LAST_ACK",
+ "TIME_WAIT"
+};
+*/
+/******************************************************************************
+ * FunctionName : debug
+ * Parameters :
+ * Returns :
+*******************************************************************************/
+void print_udp_pcb(void)
+{
+ struct udp_pcb *pcb;
+ bool prt_none = true;
+ rtl_printf("UDP pcbs:\n");
+ for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
+ rtl_printf("flg:%02x\t" IPSTR ":%d\t" IPSTR ":%d\trecv:%p\n", pcb->flags, IP2STR(&pcb->local_ip), pcb->local_port, IP2STR(&pcb->remote_ip), pcb->remote_port, pcb->recv );
+ prt_none = false;
+ };
+ if(prt_none) rtl_printf("none\n");
+}
+/******************************************************************************
+ * FunctionName : debug
+ * Parameters :
+ * Returns :
+*******************************************************************************/
+void print_tcp_pcb(void)
+{
+ struct tcp_pcb *pcb;
+ rtl_printf("Active PCB states:\n");
+ bool prt_none = true;
+ for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
+ rtl_printf("Port %d|%d\tflg:%02x\ttmr:%p\t%s\n", pcb->local_port, pcb->remote_port, pcb->flags, pcb->tmr, tcp_state_str[pcb->state]);
+ prt_none = false;
+ };
+ if(prt_none) rtl_printf("none\n");
+ rtl_printf("Listen PCB states:\n");
+ prt_none = true;
+ for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) {
+ rtl_printf("Port %d|%d\tflg:%02x\ttmr:%p\t%s\n", pcb->local_port, pcb->remote_port, pcb->flags, pcb->tmr, tcp_state_str[pcb->state]);
+ prt_none = false;
+ };
+ if(prt_none) rtl_printf("none\n");
+ rtl_printf("TIME-WAIT PCB states:\n");
+ prt_none = true;
+ for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
+ rtl_printf("Port %d|%d\tflg:%02x\ttmr:%p \t%s\n", pcb->local_port, pcb->remote_port, pcb->flags, pcb->tmr, tcp_state_str[pcb->state]);
+ prt_none = false;
+ };
+ if(prt_none) rtl_printf("none\n");
+}
+/******************************************************************************
+ * FunctionName : debug
+ * Parameters :
+ * Returns :
+*******************************************************************************/
+static void fATLW(int argc, char *argv[]) // Info Lwip
+{
+ (void) argc; (void) argv;
+ print_udp_pcb();
+ print_tcp_pcb();
+}
+
+//------------------------------------------------------------------------------
+// GPIO Info
+//------------------------------------------------------------------------------
+static void fATGI(int argc, char *argv[])
+{
+ (void) argc; (void) argv;
+ int i;
+ for (i = 0; i < _PORT_MAX; i++)
+ printf("Port %c state: 0x%04x\n", i + 'A', GPIOState[i]);
+}
+//------------------------------------------------------------------------------
+// Deep sleep
+//------------------------------------------------------------------------------
+static void fATDS(int argc, char *argv[])
+{
+ uint32 sleep_ms = 10000;
+ if(argc > 1) sleep_ms = atoi(argv[1]);
+#if 0 // WakeUp PB_1
+ if(argc > 2) {
+ printf("%u ms waiting low level on PB_1 before launching Deep-Sleep...\n", sleep_ms);
+ // turn off log uart
+ HalDeinitLogUart(); // sys_log_uart_off();
+
+ // initialize wakeup pin
+ gpio_t gpio_wake;
+ gpio_init(&gpio_wake, PB_1);
+ gpio_dir(&gpio_wake, PIN_INPUT);
+ gpio_mode(&gpio_wake, PullDown);
+ TickType_t sttime = xTaskGetTickCount();
+
+ do {
+ if(gpio_read(&gpio_wake) == 0) {
+ // Enter deep sleep... Wait give rising edge at PB_1 to wakeup system.
+ deepsleep_ex(DSLEEP_WAKEUP_BY_GPIO, 0);
+ };
+ vTaskDelay(1);
+ } while(xTaskGetTickCount() - sttime < sleep_ms);
+ HalInitLogUart(); // sys_log_uart_on();
+ printf("No set pin low in deep sleep!\n");
+ }
+ else {
+ printf("Deep-Sleep %u ms\n", sleep_ms);
+ HalLogUartWaitTxFifoEmpty();
+ // Enter deep sleep... Wait timer ms
+ deepsleep_ex(DSLEEP_WAKEUP_BY_TIMER, sleep_ms);
+ }
+#else
+ HalLogUartWaitTxFifoEmpty();
+ deepsleep_ex(DSLEEP_WAKEUP_BY_TIMER, sleep_ms);
+#endif
+}
+/*------------------------------------------------------------------------------
+ * power saving mode
+ *----------------------------------------------------------------------------*/
+static void fATSP(int argc, char *argv[])
+{
+ if(argc > 2) {
+ switch (argv[1][0]) {
+ case 'a': // acquire
+ {
+ acquire_wakelock(atoi(argv[2]));
+ break;
+ }
+ case 'r': // release
+ {
+ release_wakelock(atoi(argv[2]));
+ break;
+ }
+ };
+ };
+ printf("WakeLock Status %d\n", pmu_get_wakelock_status());
+}
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+MON_RAM_TAB_SECTION COMMAND_TABLE console_commands_at[] = {
+ {"ATST", 0, fATST, ": Memory info"},
+ {"ATLW", 0, fATLW, ": LwIP Info"},
+ {"ATGI", 0, fATGI, ": GPIO Info"},
+ {"ATSB", 1, fATSB, "=[,COUNT(dec)]: Dump byte register"},
+ {"ATSD", 1, fATSD, "=[,COUNT(dec)]: Dump dword register"},
+ {"ATSW", 2, fATSW, "=,: Set register"},
+ {"ATDS", 0, fATDS, "=[TIME(ms)]: Deep sleep"},
+ {"ATSP", 0, fATSP, "=,: Power"}
+};
+
+#endif //#ifdef CONFIG_AT_USR
diff --git a/RTLGDB/Project/console/flash_tst.c b/RTLGDB/Project/console/flash_tst.c
new file mode 100644
index 0000000..1de3193
--- /dev/null
+++ b/RTLGDB/Project/console/flash_tst.c
@@ -0,0 +1,38 @@
+/*
+ * flash_tst.c
+ *
+ * Created on: 10/04/2017
+ * Author: pvvx
+ */
+
+#include
+#include "rtl8195a.h"
+#include "flash_api.h"
+#include "rtl8195a/rtl_libc.h"
+
+extern void dump_bytes(uint32 addr, int size);
+
+static void FlashDump(int argc, char *argv[]) {
+ if (argc > 1) {
+ int addr;
+ sscanf(argv[1], "%x", &addr);
+ int size = 16;
+ if (argc > 2) {
+ size = atoi(argv[2]);
+ if (size <= 0 || size > 16384) {
+ size = 16;
+ };
+ };
+ flash_turnon();
+ dump_bytes(addr + SPI_FLASH_BASE, size);
+ SpicDisableRtl8195A();
+ }
+}
+
+MON_RAM_TAB_SECTION COMMAND_TABLE console_flash_tst[] = {
+ {"FLASHDB", 1, FlashDump, "=[,size]: Flash Dump"}
+};
+
+
+
+
diff --git a/RTLGDB/Project/console/gpio_irq_test.c b/RTLGDB/Project/console/gpio_irq_test.c
new file mode 100644
index 0000000..6ca7ae2
--- /dev/null
+++ b/RTLGDB/Project/console/gpio_irq_test.c
@@ -0,0 +1,99 @@
+/*
+ * test.c
+ *
+ * Created on: 12 марта 2017 г.
+ * Author: PVV
+ */
+
+#include
+#include "device.h"
+#include "gpio_api.h" // mbed
+#include "gpio_irq_api.h" // mbed
+#include "gpio_irq_ex_api.h" // mbed
+#include "timer_api.h"
+#include "diag.h"
+#include "main.h"
+
+#include "hal_diag.h"
+#include "rtl8195a/rtl_libc.h"
+
+#define GPIO_LED_PIN PA_4
+#define GPIO_IRQ_PIN PC_4
+
+gpio_irq_t gpio_btn;
+gpio_t gpio_led;
+gtimer_t my_timer;
+
+uint32_t lo_time_us, hi_time_us;
+uint32_t lo_time_cnt, hi_time_cnt;
+uint32_t old_tsf;
+uint32_t lo, hi, fr;
+
+uint32_t io_irq_count;
+
+static void gpio_demo_irq_handler(uint32_t id, gpio_irq_event event) {
+
+// gpio_irq_disable(&gpio_btn);
+ io_irq_count++;
+ uint32_t new_tsf = get_tsf();
+ uint32_t delta_us = (uint32_t) new_tsf - (uint32_t) old_tsf;
+ if (event & 1) {
+ lo_time_us += delta_us;
+ lo_time_cnt++;
+ gpio_irq_set(&gpio_btn, IRQ_LOW, 1);
+ } else {
+ hi_time_us += delta_us;
+ hi_time_cnt++;
+ gpio_irq_set(&gpio_btn, IRQ_HIGH, 1);
+ }
+ old_tsf = new_tsf;
+// gpio_irq_enable(&gpio_btn);
+}
+
+static void timer1_timeout_handler(uint32_t id) {
+
+ if (lo_time_cnt && hi_time_cnt) {
+ lo = lo_time_us / lo_time_cnt;
+ hi = hi_time_us / hi_time_cnt;
+ fr = hi + lo;
+ lo_time_cnt = 0;
+ lo_time_us = 0;
+ hi_time_cnt = 0;
+ hi_time_us = 0;
+ printf("Period: %lu us, Lo: %lu us, Hi: %lu us\n", fr, lo, hi);
+ }
+}
+
+/**
+ * @brief Main program.
+ * @param None
+ * @retval None
+ */
+static void fATTT(int argc, char *argv[]) {
+
+ lo_time_cnt = 0;
+ lo_time_us = 0;
+ hi_time_cnt = 0;
+ hi_time_us = 0;
+
+ // Init LED control pin
+ gpio_init(&gpio_led, GPIO_LED_PIN);
+ gpio_dir(&gpio_led, PIN_OUTPUT); // Direction: Output
+ gpio_mode(&gpio_led, PullNone); // No pull
+ gpio_write(&gpio_led, 0);
+
+ // Initial Push Button pin as interrupt source
+ gpio_irq_init(&gpio_btn, GPIO_IRQ_PIN, gpio_demo_irq_handler,
+ (uint32_t) (&gpio_led));
+ gpio_irq_set(&gpio_btn, IRQ_FALL, 1); // Falling Edge Trigger
+ gpio_irq_enable(&gpio_btn);
+
+ // Initial a periodical timer
+ gtimer_init(&my_timer, TIMER1);
+ gtimer_start_periodical(&my_timer, 1000000, (void*) timer1_timeout_handler,
+ (uint32_t) &gpio_led);
+}
+
+MON_RAM_TAB_SECTION COMMAND_TABLE console_commands_test[] = { { "ATTT", 0,
+ fATTT, ": Test" } };
+
diff --git a/RTLGDB/Project/console/power_tst.c b/RTLGDB/Project/console/power_tst.c
new file mode 100644
index 0000000..d48cdd3
--- /dev/null
+++ b/RTLGDB/Project/console/power_tst.c
@@ -0,0 +1,38 @@
+/*
+ * power_tst.c
+ *
+ * Created on: 04 апр. 2017 г.
+ * Author: PVV
+ */
+
+#include "rtl8195a.h"
+#include "freertos_pmu.h"
+#include "rtl8195a/rtl_libc.h"
+/*------------------------------------------------------------------------------
+ * power saving mode
+ *----------------------------------------------------------------------------*/
+void fATSP(int argc, char *argv[])
+{
+ if(argc > 2) {
+ switch (argv[1][0]) {
+ case 'a': // acquire
+ {
+ acquire_wakelock(atoi(argv[2]));
+ break;
+ }
+ case 'r': // release
+ {
+ release_wakelock(atoi(argv[2]));
+ break;
+ }
+ }
+ }
+ printf("WakeLock Status %d\n", pmu_get_wakelock_status());
+}
+
+
+MON_RAM_TAB_SECTION COMMAND_TABLE console_commands_pwrs[] = {
+ {"ATSP", 0, fATSP, "=,: Power"}
+};
+
+
diff --git a/RTLGDB/Project/console/pwm_tst.c b/RTLGDB/Project/console/pwm_tst.c
new file mode 100644
index 0000000..987ebe2
--- /dev/null
+++ b/RTLGDB/Project/console/pwm_tst.c
@@ -0,0 +1,54 @@
+/*
+ * pwm_tst.c
+ *
+ * Created on: 19/04/2017.
+ * Author: pvvx
+ */
+
+#include
+#include "rtl8195a.h"
+#include "FreeRTOS.h"
+#include "rtl8195a/rtl_libc.h"
+
+//#include "device.h"
+#include "pwmout_api.h" // mbed
+//#include "main.h"
+#include "web_utils.h"
+#include "objects.h"
+#include "pinmap.h"
+
+extern const PinMap PinMap_PWM[];
+extern uint32_t gTimerRecord;
+
+HAL_PWM_ADAPTER pwm_hal_adp;
+
+static void fATPWM(int argc, char *argv[]) {
+
+ uint8_t pin = ahextoul(argv[1]);
+ uint32_t period = ahextoul(argv[2]);
+ uint32_t pulse = ahextoul(argv[3]);
+
+ uint32_t peripheral = pinmap_peripheral(pin, PinMap_PWM);
+
+ if(pwm_hal_adp.enable) {
+ HAL_Pwm_Disable(&pwm_hal_adp);
+ gTimerRecord &= ~(1 << pwm_hal_adp.gtimer_id);
+ rtl_memset((void *)&pwm_hal_adp, 0, sizeof(HAL_PWM_ADAPTER));
+ };
+ if((period) && (unlikely(peripheral != NC))
+ && (HAL_Pwm_Init(&pwm_hal_adp, RTL_GET_PERI_IDX(peripheral), RTL_GET_PERI_SEL(peripheral)) == HAL_OK)) {
+ HAL_Pwm_SetDuty(&pwm_hal_adp, period, pulse);
+ HAL_Pwm_Enable(&pwm_hal_adp);
+ } else {
+ printf("Error parameters!");
+ };
+}
+
+//------------------------------------------------------------------------------
+// atpwm=34,1048575,524287
+// atpwm=34,122,61 (8.187kHz)
+// atsw 40000368 85001002 (8.187kHz)
+// atsd 40000360 6
+MON_RAM_TAB_SECTION COMMAND_TABLE console_commands_pwm[] = {
+ { "ATPWM", 3, fATPWM, "=,,: PWM Test" }
+};
diff --git a/RTLGDB/Project/console/sd_fat.c b/RTLGDB/Project/console/sd_fat.c
new file mode 100644
index 0000000..e36c7f3
--- /dev/null
+++ b/RTLGDB/Project/console/sd_fat.c
@@ -0,0 +1,383 @@
+/*
+ * sd_fat.c
+ *
+ * Created on: 17 дек. 2016 г.
+ * Author: PVV
+ */
+#include "rtl8195a.h"
+
+#ifdef CONFIG_SDIO_HOST_EN
+
+#include "rtl8195a_sdio_host.h"
+#include "hal_sdio_host.h"
+#include "sd.h"
+#include "sdio_host.h"
+#include "pinmap.h"
+#include "sdcard.h"
+//#include "ff.h"
+//#include "fatfs_ext/inc/ff_driver.h"
+#include "rtl8195a/os.h"
+#include "at_cmd/log_service.h"
+
+
+//extern ll_diskio_drv SD_disk_Driver;
+
+char *logical_drv = "0:/";
+
+#define START_CHAR_DISK '0'
+
+typedef struct _msftm_td {
+ unsigned short day :5;
+ unsigned short month :4;
+ unsigned short year :7;
+} msftm_d;
+
+typedef struct _msftm_tt {
+ unsigned short sec :5;
+ unsigned short min :6;
+ unsigned short hour :5;
+} msftm_t;
+
+typedef union {
+ unsigned short w;
+ msftm_d d;
+} msftm_td;
+
+typedef union {
+ unsigned short w;
+ msftm_t t;
+} msftm_tt;
+uint8_t * month[12] = { "Jan" , "Feb" , "Mar" , "Apr" , "May" , "Jun" , "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+/*
+ * MS files times
+ */
+int ms_ftime(unsigned short td, unsigned short tt, struct os_tm *tm) {
+ msftm_td d;
+ msftm_tt t;
+ d.w = td;
+ t.w = tt;
+ tm->year = d.d.year + 1980;
+ tm->month = d.d.month;
+ tm->day = d.d.day;
+ tm->hour = t.t.hour;
+ tm->min = t.t.min;
+ tm->sec = t.t.sec << 1;
+ if (tm->month > 11 || tm->hour > 23 || tm->min > 59 || tm->sec > 59) {
+ return 0;
+ }
+ return 1;
+}
+/*
+ * MS files attr
+ */
+uint8_t * ms_fattr(uint8_t *s, uint8_t attr) {
+ memset(s, '-', 7);
+ if (attr & AM_ARC)
+ s[0] = 'a';
+ if (attr & AM_DIR)
+ s[1] = 'd';
+ if (attr & AM_LFN)
+ s[2] = 'l';
+ if (attr & AM_VOL)
+ s[3] = 'v';
+ if (attr & AM_SYS)
+ s[4] = 's';
+ if (attr & AM_HID)
+ s[5] = 'h';
+ if (attr & AM_RDO)
+ s[6] = 'r';
+ s[7] = 0;
+ return s;
+}
+
+/*
+ * Linux files attr
+ */
+uint8_t * ux_fattr(uint8_t *s, uint8_t attr) {
+ memset(s, '-', 10);
+ if (attr & AM_DIR) {
+ s[0] = 'd';
+// s[3] = 'x';
+// s[6] = 'x';
+// s[9] = 'x';
+ }
+ if (!(attr & AM_VOL)) {
+// {
+ s[1] = 'r';
+ s[4] = 'r';
+ s[7] = 'r';
+ if (!(attr & AM_RDO)) {
+ s[2] = 'w';
+ s[5] = 'w';
+ s[8] = 'w';
+ }
+ }
+// if(attr & AM_VOL) s[3] = 'x';
+ if (!(attr & AM_SYS))
+ s[3] = 'x';
+ if (!(attr & AM_HID))
+ s[6] = 'x';
+ if (!(attr & AM_ARC))
+ s[9] = 'x';
+ s[10] = 0;
+ return s;
+}
+
+FATFS * sd_mount(void) {
+ FATFS * m_fs = NULL;
+ // Рнициализация I/O SDIOH
+ if (HalGetChipId() != CHIP_ID_8195AM) {
+ GPIOState[0] &= ~((1 << 8) - 1);
+ HAL_GPIO_PullCtrl(PA_0, PullUp); // D2
+ HAL_GPIO_PullCtrl(PA_1, PullUp); // D3
+ HAL_GPIO_PullCtrl(PA_2, PullUp); // CMD
+ HAL_GPIO_PullCtrl(PA_3, PullNone); // CLK
+ HAL_GPIO_PullCtrl(PA_4, PullUp); // D0
+ HAL_GPIO_PullCtrl(PA_5, PullUp); // D1
+ HAL_GPIO_PullCtrl(PA_6, PullDown); // SD card removed
+ HAL_GPIO_PullCtrl(PA_7, PullDown); // WP enable
+ vTaskDelay(1);
+ };
+ int8_t ret = SD_Init();
+ if (ret < SD_NODISK) { // sdio_sd_init();
+ if (sdio_sd_status() >= 0 && sdio_status == SDIO_SD_OK) {
+ sdio_sd_getProtection();
+#if CONFIG_DEBUG_LOG > 2
+ // чтение информации о SD карте
+ printf("\nSD CSD: ");
+ for (int i = 0; i < 16; i++)
+ printf("%02x", SdioHostAdapter.Csd[i]);
+ uint32_t i = sdio_sd_getCapacity();
+ printf("\nSD Capacity: %d sectors (%d GB | %d MB | %d KB)\n", i,
+ i >> 21, i >> 11, i >> 1);
+#endif
+ m_fs = (FATFS *) malloc(sizeof(FATFS));
+ if (m_fs != NULL) {
+ memset(m_fs, 0, sizeof(FATFS));
+ int drv_num = FATFS_RegisterDiskDriver(&SD_disk_Driver);
+ if (drv_num >= 0) {
+ *logical_drv = (char) drv_num + START_CHAR_DISK;
+ if (f_mount(m_fs, logical_drv, 1) == FR_OK) {
+ m_fs->drv = (BYTE) drv_num;
+#if CONFIG_DEBUG_LOG > 3
+ printf("SD disk:%c mounted\n", logical_drv[0], m_fs);
+#endif
+ } else {
+#if CONFIG_DEBUG_LOG > 2
+ printf("SD disk mount failed!\n");
+#endif
+ FATFS_UnRegisterDiskDriver(drv_num);
+ free(m_fs);
+ m_fs = NULL;
+ }
+ } else {
+#if CONFIG_DEBUG_LOG > 2
+ printf("SD Register Disk Driver failed!\n");
+#endif
+ free(m_fs);
+ m_fs = NULL;
+ }
+ } else {
+#if CONFIG_DEBUG_LOG > 2
+ printf("Malloc failed!\n");
+#endif
+ }
+ } else {
+#if CONFIG_DEBUG_LOG > 2
+ printf("SD Error (%d) get status!\n", sdio_status);
+#endif
+ }
+ } else {
+#if CONFIG_DEBUG_LOG > 2
+ printf("SD Init Error (%d)!\n", ret);
+#endif
+ }
+ return m_fs;
+}
+
+void sd_unmount(FATFS *m_fs) {
+ if (m_fs != NULL) {
+#if CONFIG_DEBUG_LOG > 2
+ printf("unmount (%d)\n", f_mount(NULL, logical_drv, 1));
+#else
+ f_mount(NULL, logical_drv, 1);
+#endif
+ FATFS_UnRegisterDiskDriver(m_fs->drv);
+ free(m_fs);
+ }
+ pin_mode(PA_6, PullUp); // SD card removed
+ pin_mode(PA_7, PullUp); // WP enable
+ vTaskDelay(1);
+ SD_DeInit(); // sdio_sd_deinit();
+}
+
+void read_file_test(char* file_name) {
+ FIL *f = malloc(sizeof(FIL));
+ if (f_open(f, file_name, FA_READ) == FR_OK) {
+ char * buf = malloc(2048);
+ unsigned int bytesread =0;
+ unsigned int totalread=0;
+ do {
+ if (f_read(f, buf, 2048, &bytesread) != FR_OK) {
+ totalread += bytesread;
+ printf("Read error!");
+ break;
+ }
+ totalread += bytesread;
+ }
+ while (bytesread !=0);
+ free(buf);
+ f_close(f);
+ } else {
+ printf("No open file!");
+ }
+ free(f);
+}
+
+
+static void fATHF(int argc, char *argv[]) {
+ uint8 buf[512];
+ FATFS * fs = sd_mount();
+ if (fs != NULL) {
+ uint8_t * pbuf = (uint8_t *) malloc(512); // char *lfn = malloc (_MAX_LFN + 1);
+ if (pbuf != NULL) {
+ DIR dir;
+ FILINFO fno;
+ fno.lfname = (TCHAR*) pbuf;
+ fno.lfsize = 512;
+ uint8_t * sdir;
+ if(argc > 1
+ && argv[1] != NULL
+ && (sdir = (uint8_t *) malloc(strlen(argv[1]) + 4)) != NULL )
+ strcpy(strcpy(sdir, logical_drv) + 3, argv[1]);
+ else sdir = logical_drv;
+ if (f_opendir(&dir, sdir) == FR_OK) {
+ while (f_readdir(&dir, &fno) == FR_OK && fno.fname[0] != 0) {
+ if ((fno.fattrib & AM_VOL)==0 && fno.fsize > 0) {
+ if (*fno.lfname) {
+ strcpy(strcpy(buf, logical_drv) + 3, fno.lfname);
+ } else {
+ strcpy(strcpy(buf, logical_drv) + 3, fno.fname);
+ }
+ TickType_t t1 = xTaskGetTickCount();
+ read_file_test(buf);
+ t1 = xTaskGetTickCount() - t1;
+ if(t1 == 0) t1 = 1;
+ printf("%u kbytes/sec\t%s\n", t1, buf);
+ }
+ }
+ } else
+ printf("FATFS: Open dir fail!\n");
+ free(pbuf);
+ if((void *)sdir != (void *)logical_drv) free(sdir);
+ }
+ }
+ sd_unmount(fs);
+
+}
+/* Test SD */
+static void fATHS(int argc, char *argv[]) {
+ // HalPinCtrlRtl8195A(UART0,0,0);
+ // HalPinCtrlRtl8195A(UART1,0,0);
+#if CONFIG_DEBUG_LOG > 4
+ ConfigDebugErr = -1;
+ ConfigDebugInfo = -1;
+ ConfigDebugWarn = -1;
+ CfgSysDebugErr = -1;
+ CfgSysDebugInfo = -1;
+ CfgSysDebugWarn = -1;
+#endif
+
+#if DEBUG_AT_USER_LEVEL > 3
+ printf("ATHS: dir\n");
+#endif
+ FATFS * fs = sd_mount();
+ if (fs != NULL) {
+ uint8_t * pbuf = (uint8_t *) malloc(512); // char *lfn = malloc (_MAX_LFN + 1);
+ if (pbuf != NULL) {
+ DIR dir;
+ FILINFO fno;
+ struct os_tm tm;
+ fno.lfname = (TCHAR*) pbuf;
+ fno.lfsize = 512;
+ uint8_t * sdir;
+ if(argc > 1
+ && argv[1] != NULL
+ && (sdir = (uint8_t *) malloc(strlen(argv[1]) + 4)) != NULL )
+ strcpy(strcpy(sdir, logical_drv) + 3, argv[1]);
+ else sdir = logical_drv;
+ printf("\ndir %s\n", sdir);
+ if (f_opendir(&dir, sdir) == FR_OK) {
+ while (f_readdir(&dir, &fno) == FR_OK && fno.fname[0] != 0) {
+ int srtlen = 0;
+ {
+ uint8_t buf[12];
+ srtlen += printf(ux_fattr(buf, fno.fattrib));
+ }
+ srtlen += printf(" 0");
+ if (fno.fattrib & AM_VOL)
+ printf(" volume");
+ else if (fno.fattrib & AM_SYS)
+ printf(" system");
+ else
+ printf(" none ");
+ srtlen += 7;
+ if (fno.fattrib & AM_HID)
+ printf(" hidden");
+ else
+ printf(" none ");
+ srtlen += 7;
+ srtlen += printf(" %d", fno.fsize);
+ while (srtlen < 37)
+ srtlen += printf(" ");
+ ms_ftime(fno.fdate, fno.ftime, &tm);
+ srtlen += printf(" %04d-%02d-%02d %02d:%02d:%02d ", tm.year,
+ tm.month, tm.day, tm.hour, tm.min, tm.sec);
+ if (*fno.lfname) {
+ srtlen += printf(fno.lfname);
+ //fnlen = fno.lfsize;
+ } else {
+ srtlen += printf(fno.fname);
+ //fnlen = fno.fsize;
+ }
+ printf("\n");
+ };
+ printf("\n");
+ f_closedir(&dir);
+ } else
+ printf("FATFS: Open dir fail!\n");
+ free(pbuf);
+ if((void *)sdir != (void *)logical_drv) free(sdir);
+ }
+ }
+ sd_unmount(fs);
+
+ /*
+ } else
+ printf("FATFS: Malloc fail!\n");
+ f_mount(NULL, logical_drv, 1);
+ } else
+ printf("FATFS mount logical drive fail!\n");
+ FATFS_UnRegisterDiskDriver(drv_num);
+ } else
+ printf("Register disk driver to FATFS fail.\n");
+ free(m_fs);
+ } else
+ printf("FATFS: Malloc fail!\n");
+ } else
+ printf("SD Init fail!\n");
+ pin_mode(PA_6, PullUp); // SD card removed
+ pin_mode(PA_7, PullUp); // WP enable
+ vTaskDelay(5);
+
+ SD_DeInit(); // sdio_sd_deinit();
+ */
+}
+
+
+MON_RAM_TAB_SECTION COMMAND_TABLE console_commands_dscard[] = {
+ {"ATHS", 0, fATHS, "=[dir]: SD test"},
+ {"ATHF", 0, fATHF, "=[dir]: SD file read"}
+};
+
+#endif // CONFIG_SDIO_HOST_EN
diff --git a/RTLGDB/Project/console/spi_tst.c b/RTLGDB/Project/console/spi_tst.c
new file mode 100644
index 0000000..72770fa
--- /dev/null
+++ b/RTLGDB/Project/console/spi_tst.c
@@ -0,0 +1,83 @@
+/*
+ * spi_test.c
+ */
+#include
+#include "rtl8195a.h"
+#include "spi_api.h"
+#include "spi_ex_api.h"
+#include "rtl8195a/rtl_libc.h"
+
+#define SPI0_MOSI PC_2
+#define SPI0_MISO PC_3
+#define SPI0_SCLK PC_1
+#define SPI0_CS PC_0
+
+spi_t spi_master;
+
+static void show_reg_spi(int i) {
+ rtl_printf("Regs SPI:\n");
+ for(int x = 0; x < 64 ; x += 4) {
+ rtl_printf("0x%08x ", HAL_SSI_READ32(i, x));
+ if((x & 0x0F) == 0x0C) rtl_printf("\n");
+ }
+}
+
+
+static void fATSSI(int argc, char *argv[])
+{
+ int len = 128;
+ int count = 32;
+ int clk = 1000000;
+ int ssn = 0;
+ if(argc > 1) {
+ len = atoi(argv[1]);
+ if(len > 32768 || len <= 0) {
+ len = 128;
+ error_printf("%s: len = %u!\n", __func__, len);
+ };
+ };
+ if(argc > 2) {
+ count = atoi(argv[2]);
+ if(count > 10000 || count <= 0) {
+ count = 32;
+ error_printf("%s: count = %u!\n", __func__, count);
+ };
+ };
+ if(argc > 3) {
+ clk = atoi(argv[3]);
+ if(clk <= 0) {
+ clk = 1000000;
+ error_printf("%s: clk = %u!\n", __func__, clk);
+ };
+ };
+ if(argc > 4) {
+ ssn = atoi(argv[4]);
+ if(ssn > 7 || ssn < 0) {
+ ssn = 0;
+ error_printf("%s: ssn = %u!\n", __func__, ssn);
+ };
+ };
+ char* buff = pvPortMalloc(len);
+ if(buff) {
+ spi_init(&spi_master, SPI0_MOSI, SPI0_MISO, SPI0_SCLK, SPI0_CS); // CS заданный тут нигде не используется
+ spi_format(&spi_master, 16, 3, 0);
+ spi_frequency(&spi_master, clk);
+ spi_slave_select(&spi_master, ssn); // выбор CS
+ for(int i = 0; i < len; i++) buff[i] = (char)i;
+ while(count--) {
+ spi_master_write_stream(&spi_master, buff, len);
+ while(spi_busy(&spi_master));
+ rtl_printf("Master write: %d\n", count);
+ };
+// show_reg_spi(spi_master.spi_adp.Index);
+ spi_free(&spi_master);
+ free(buff);
+ }
+ else {
+ error_printf("%s: error malloc!\n", __func__);
+ };
+}
+
+MON_RAM_TAB_SECTION COMMAND_TABLE console_commands_spitst[] = {
+ {"ATSSI", 0, fATSSI, "=[len[,count[,clk[,ssn]]]]: Spi test"}
+};
diff --git a/RTLGDB/Project/console/wifi_console.c b/RTLGDB/Project/console/wifi_console.c
new file mode 100644
index 0000000..38ca46c
--- /dev/null
+++ b/RTLGDB/Project/console/wifi_console.c
@@ -0,0 +1,353 @@
+/*
+ * wifi_console.c
+ *
+ * Created on: 03/04/2017
+ * Author: pvvx
+ */
+
+#include
+#include "FreeRTOS.h"
+#include "diag.h"
+#include "wifi_api.h"
+#include "wifi_conf.h"
+#include "rtl8195a/rtl_libc.h"
+#include "hal_platform.h"
+#include "freertos_pmu.h"
+
+#include "section_config.h"
+#include "hal_diag.h"
+#include "lwip/netif.h"
+
+
+extern struct netif xnetif[NET_IF_NUM];
+
+//==========================================================
+//--- CONSOLE --------------------------
+
+// ATPN=[,password[,encryption[,auto reconnect[,reconnect pause]]]: WIFI Connect to AP
+static void fATPN(int argc, char *argv[]){
+ if(argc > 1) {
+ if(argv[1][0] == '?') {
+ show_wifi_st_cfg();
+ }
+ else {
+ strncpy(wifi_st_cfg.ssid, argv[1], NDIS_802_11_LENGTH_SSID);
+ int pswlen;
+ if(argc > 2) {
+ pswlen = strlen(wifi_st_cfg.password);
+ strncpy(wifi_st_cfg.password, argv[2], NDIS_802_11_LENGTH_SSID);
+ if(pswlen > 7) {
+ wifi_st_cfg.security = IDX_SECURITY_WPA2_AES_PSK;
+ }
+ else if(!pswlen) {
+ wifi_st_cfg.security = IDX_SECURITY_OPEN;
+ }
+ else {
+ printf("password len < 8!\n");
+ wifi_st_cfg.security = IDX_SECURITY_OPEN;
+ }
+ }
+ else {
+ // default
+ wifi_st_cfg.password[0] = 0;
+ wifi_st_cfg.security = IDX_SECURITY_OPEN;
+ }
+ if(argc > 3) {
+ if(pswlen > 7) {
+ wifi_st_cfg.security = atoi(argv[3]);
+ }
+ else {
+ printf("password len < 8!\n");
+ wifi_st_cfg.security = IDX_SECURITY_OPEN;
+ }
+ }
+ if(argc > 4) {
+ wifi_st_cfg.autoreconnect = atoi(argv[4]);
+ }
+ else wifi_st_cfg.autoreconnect = 0;
+ if(argc > 5) {
+ wifi_st_cfg.reconnect_pause = atoi(argv[5]);
+ }
+ else wifi_st_cfg.reconnect_pause = 5;
+ show_wifi_st_cfg();
+#if CONFIG_WLAN_CONNECT_CB
+ connect_close();
+#endif
+ wifi_run(wifi_run_mode | RTW_MODE_STA);
+ }
+ }
+}
+
+// ATPA=[,password[,encryption[,channel[,hidden[,max connections]]]]]: Start WIFI AP
+static void fATPA(int argc, char *argv[]){
+ if(argc > 1) {
+ if(argv[1][0] == '?') {
+ show_wifi_ap_cfg();
+ }
+ else {
+ strncpy(wifi_ap_cfg.ssid, argv[1], NDIS_802_11_LENGTH_SSID);
+ if(argc > 2) {
+ strncpy(wifi_ap_cfg.password, argv[2], NDIS_802_11_LENGTH_SSID);
+ int i = strlen(wifi_ap_cfg.password);
+ if(i > 7) {
+ wifi_ap_cfg.security = 1; // IDX_SECURITY_WPA2_AES_PSK;
+ }
+ else if(i == 0) {
+ wifi_ap_cfg.security = 0; // IDX_SECURITY_OPEN;
+ }
+ else {
+ printf("password len < 8!\n");
+ wifi_ap_cfg.security = 0; // IDX_SECURITY_OPEN;
+ }
+ }
+ else {
+ wifi_ap_cfg.password[0] = 0;
+ wifi_ap_cfg.security = 0; // IDX_SECURITY_OPEN;
+ }
+ if(argc > 3) {
+ wifi_ap_cfg.security = (argv[3][0] == '0')? 0 : 1; //RTW_SECURITY_OPEN : RTW_SECURITY_WPA2_AES_PSK;
+ }
+ if(argc > 4) {
+ wifi_ap_cfg.channel = atoi(argv[4]);
+ }
+ else wifi_ap_cfg.channel = 1;
+ if(argc > 5) {
+ wifi_ap_cfg.ssid_hidden = atoi(argv[5]);
+ }
+ else wifi_ap_cfg.ssid_hidden = 0;
+
+ if(argc > 6) {
+ wifi_ap_cfg.max_sta = atoi(argv[6]);
+ }
+ else wifi_ap_cfg.max_sta = 3;
+
+ show_wifi_ap_cfg();
+#if CONFIG_WLAN_CONNECT_CB
+ connect_close();
+#endif
+ wifi_run(wifi_run_mode | RTW_MODE_AP);
+ }
+ }
+}
+
+// WIFI Connect, Disconnect
+static void fATWR(int argc, char *argv[]){
+ rtw_mode_t mode = RTW_MODE_NONE;
+ if(argc > 1) mode = atoi(argv[1]);
+#if CONFIG_WLAN_CONNECT_CB
+ connect_close();
+#endif
+ wifi_run(mode);
+}
+
+#if CONFIG_WLAN_CONNECT_CB
+// Close connections
+static void fATOF(int argc, char *argv[]){
+ connect_close();
+}
+
+// Open connections
+static void fATON(int argc, char *argv[]){
+ connect_start();
+}
+#endif
+
+static void fATWI(int argc, char *argv[]) {
+#if 1
+ if(argc > 2) {
+ uint8_t c = argv[1][0] | 0x20;
+ if(c == 's') {
+ int i = atoi(argv[2]);
+ printf("Save configs(%d)..\n", i);
+ write_wifi_cfg(atoi(argv[2]));
+ }
+ else if(c == 'l') {
+ wifi_cfg.load_flg = atoi(argv[2]);
+ }
+ else if(c == 'm') {
+ wifi_cfg.mode = atoi(argv[2]);
+ }
+ }
+#endif
+ rtw_wifi_setting_t Setting;
+ if((wifi_run_mode & RTW_MODE_AP)
+ && wifi_get_setting(wlan_ap_name, &Setting) == 0) {
+ wifi_show_setting(wlan_ap_name, &Setting);
+// show_wifi_ap_ip();
+ printf("\tIP: " IPSTR "\n\n", IP2STR(&xnetif[WLAN_AP_NETIF_NUM].ip_addr));
+//#if CONFIG_DEBUG_LOG > 1
+ show_wlan_info(WLAN_AP_NETIF_NUM);
+//#endif
+ }
+ if((wifi_run_mode & RTW_MODE_STA)
+ && wifi_get_setting(wlan_st_name, &Setting) == 0) {
+ wifi_show_setting(wlan_st_name, &Setting);
+// show_wifi_st_ip();
+ printf("\tIP: " IPSTR "\n\n", IP2STR(&xnetif[WLAN_ST_NETIF_NUM].ip_addr));
+//#if CONFIG_DEBUG_LOG > 1
+ show_wlan_info(WLAN_ST_NETIF_NUM);
+//#endif
+ }
+ printf("\nWIFI config:\n");
+ printf(&str_rom_57ch3Dch0A[25]); // "================================\n"
+ show_wifi_cfg();
+ printf("\nWIFI AP config:\n");
+ printf(&str_rom_57ch3Dch0A[25]); // "================================\n"
+ show_wifi_ap_cfg();
+ printf("\nWIFI ST config:\n");
+ printf(&str_rom_57ch3Dch0A[25]); // "================================\n"
+ show_wifi_st_cfg();
+#if SDK_VER_NUM > 0x4000
+ if(wifi_mode & RTW_MODE_AP) {
+ printf("\nWIFI AP clients:\n");
+ printf(&str_rom_57ch3Dch0A[25]); // "================================\n"
+ show_wifi_ap_clients();
+ }
+#endif
+ printf("\n");
+}
+
+extern uint8_t rtw_power_percentage_idx;
+extern int rltk_set_tx_power_percentage(rtw_tx_pwr_percentage_t power_percentage_idx);
+
+void fATWT(int argc, char *argv[]) {
+ (void) argc; (void) argv;
+ if(argc > 1) {
+ int txpwr = atoi(argv[1]);
+ debug_printf("set tx power (%d)...\n", txpwr);
+ if(rltk_set_tx_power_percentage(txpwr) != RTW_SUCCESS) {
+ error_printf("Error set tx power (%d)!", wifi_cfg.tx_pwr);
+ }
+ }
+ printf("TX power = %d\n", rtw_power_percentage_idx);
+}
+
+//-- Test tsf (64-bits counts, 1 us step) ---
+
+//#include "hal_com_reg.h"
+#define WIFI_REG_BASE 0x40080000
+#define REG_TSFTR 0x0560
+#define REG_TSFTR1 0x0568 // HW Port 1 TSF Register
+
+#define ReadTSF_Lo32() (*((volatile unsigned int *)(WIFI_REG_BASE + REG_TSFTR)))
+#define ReadTSF_Hi32() (*((volatile unsigned int *)(WIFI_REG_BASE + REG_TSFTR1)))
+
+static uint64_t get_tsf(void)
+{
+ return *((uint64_t *)(WIFI_REG_BASE + REG_TSFTR));
+}
+
+void fATSF(int argc, char *argv[])
+{
+ (void) argc; (void) argv;
+ uint64_t tsf = get_tsf();
+ printf("\nTSF: %08x%08x\n", (uint32_t)(tsf>>32), (uint32_t)(tsf));
+}
+
+void fATWP(int argc, char *argv[]) {
+ (void) argc; (void) argv;
+ int x = 0;
+ if(argc > 1) {
+ x = atoi(argv[1]);
+ if(x == 0) {
+ acquire_wakelock(~WAKELOCK_WLAN);
+ release_wakelock(0xffff);
+ _wext_enable_powersave(0, 0, 0);
+ _wext_set_lps_dtim(0, 1);
+ } else {
+ release_wakelock(~WAKELOCK_WLAN);
+ _wext_enable_powersave(0, 1, 1);
+ _wext_set_lps_dtim(0, x);
+ }
+ }
+ else {
+ printf("DTIM: %d\n", _wext_get_lps_dtim(0));
+ }
+}
+/* -------- WiFi Scan ------------------------------- */
+static rtw_result_t scan_result_handler(internal_scan_handler_t* ap_scan_result)
+{
+ if (ap_scan_result) {
+ if(ap_scan_result->scan_cnt) {
+ printf("\nScan networks:\n\n");
+ printf("N\tType\tMAC\t\t\tSignal\tCh\tWPS\tSecyrity\tSSID\n\n");
+ for(int i = 0 ; i < ap_scan_result->scan_cnt; i++) {
+ rtw_scan_result_t* record = &ap_scan_result->ap_details[i];
+ printf("%d\t", i+1);
+ printf("%s\t", (record->bss_type == RTW_BSS_TYPE_ADHOC)? "Adhoc": "Infra");
+ printf(MAC_FMT, MAC_ARG(record->BSSID.octet));
+ printf("\t%d\t", record->signal_strength);
+ printf("%d\t", record->channel);
+ printf("%d\t", record->wps_type);
+ {
+ uint8 * s = rtw_security_to_str(record->security);
+ printf("%s\t", s);
+ if(strlen(s) < 8) printf("\t");
+ }
+ record->SSID.val[record->SSID.len] = '\0';
+ printf("%s\n", record->SSID.val);
+ }
+ }
+ } else {
+ printf("Scan networks: None!\n");
+ }
+ return RTW_SUCCESS;
+}
+/* -------- WiFi Scan ------------------------------- */
+void fATSN(int argc, char *argv[])
+{
+ (void) argc;
+ (void) argv;
+ api_wifi_scan(scan_result_handler);
+}
+
+#if defined(CONFIG_ENABLE_WPS_AP) && CONFIG_ENABLE_WPS_AP
+extern void cmd_ap_wps(int argc, char **argv);
+extern void cmd_wps(int argc, char **argv);
+//extern void cmd_wifi_on(int argc, char **argv);
+#endif
+#if CONFIG_ENABLE_P2P
+extern void cmd_wifi_p2p_start(int argc, char **argv);
+extern void cmd_wifi_p2p_stop(int argc, char **argv);
+extern void cmd_p2p_listen(int argc, char **argv);
+extern void cmd_p2p_find(int argc, char **argv);
+extern void cmd_p2p_peers(int argc, char **argv);
+extern void cmd_p2p_info(int argc, char **argv);
+extern void cmd_p2p_disconnect(int argc, char **argv);
+extern void cmd_p2p_connect(int argc, char **argv);
+extern void cmd_wifi_p2p_auto_go_start(int argc, char **argv);
+extern void cmd_p2p_peers(int argc, char **argv);
+#endif //CONFIG_ENABLE_P2P
+
+MON_RAM_TAB_SECTION COMMAND_TABLE console_cmd_wifi_api[] = {
+ {"ATPN", 1, fATPN, "=[,password[,encryption[,auto-reconnect[,reconnect pause]]]: WIFI Connect to AP"},
+ {"ATPA", 1, fATPA, "=[,password[,encryption[,channel[,hidden[,max connections]]]]]: Start WIFI AP"},
+#if defined(CONFIG_ENABLE_WPS_AP) && CONFIG_ENABLE_WPS_AP
+ {"WPS_AP", 1, cmd_ap_wps, "=[,pin]: WiFi AP WPS"},
+ {"WPS_ST", 1, cmd_wps, "=[,pin]: WiFi Station WPS"},
+#endif
+#if CONFIG_ENABLE_P2P
+ {"P2P_START", 0, cmd_wifi_p2p_start, ": p2p start" },
+ {"P2P_ASTART", 0, cmd_wifi_p2p_auto_go_start, ": p2p auto go start" },
+ {"P2P_STOP", 0, cmd_wifi_p2p_stop, ": p2p stop"},
+ {"P2P_PEERS", 0, cmd_p2p_peers, ": p2p peers" },
+ {"P2P_FIND", 0, cmd_p2p_find, ": p2p find"},
+ {"P2P_INFO", 0, cmd_p2p_info, ": p2p info"},
+ {"P2P_DISCCONNECT", 0, cmd_p2p_disconnect, ": p2p disconnect"},
+ {"P2P_CONNECT", 0, cmd_p2p_connect, ": p2p connect"},
+#endif
+ {"ATWR", 0, fATWR, "=[mode]: WIFI Mode: 0 - off, 1 - ST, 2 - AP, 3 - ST+AP"},
+#if CONFIG_WLAN_CONNECT_CB
+ {"ATON", 0, fATON, ": Open connections"},
+ {"ATOFF", 0, fATOF, ": Close connections"},
+#endif
+ {"ATWI", 0, fATWI, ": WiFi Info"},
+#if CONFIG_DEBUG_LOG > 3
+ {"ATWT", 1, fATWT, "=: WiFi tx power: 0 - 100%, 1 - 75%, 2 - 50%, 3 - 25%, 4 - 12.5%"},
+ {"ATSF", 0, fATSF, ": Get TSF value"},
+#endif
+// {"ATWP", 0, fATWP, "=[dtim]: 0 - WiFi ipc/lpc off, 1..10 - on + dtim"},
+ {"ATSN", 0, fATSN, ": Scan networks"}
+};
+
+
diff --git a/RTLGDB/Project/console/wlan_tst.c b/RTLGDB/Project/console/wlan_tst.c
new file mode 100644
index 0000000..b3f7bb5
--- /dev/null
+++ b/RTLGDB/Project/console/wlan_tst.c
@@ -0,0 +1,75 @@
+/*
+ * wlan_tst.c
+ *
+ * Created on: 10 апр. 2017 г.
+ * Author: PVV
+ */
+#include
+#include "rtl8195a.h"
+#include "FreeRTOS.h"
+#include "task.h"
+#if 1
+#include "drv_types.h" // or #include "wlan_lib.h"
+#else
+#include "wifi_constants.h"
+#include "wifi_structures.h"
+#include "wlan_lib.h" // or #include "drv_types.h"
+#endif
+
+//#include "section_config.h"
+//#include "hal_diag.h"
+#include "rtl8195a/rtl_libc.h"
+
+extern void dump_bytes(uint32 addr, int size);
+extern Rltk_wlan_t rltk_wlan_info[2]; // in wrapper.h
+
+static void tst_wlan_struct(int argc, char *argv[])
+{
+ (void)argc; (void)argv;
+ printf("Test: sizeof(struct _ADAPTER) = %d\n", sizeof(struct _ADAPTER)); //6088
+ printf("mlmeextpriv\t+%d\n", offsetof(struct _ADAPTER, mlmeextpriv)); //+1256
+ printf("TSFValue\t+%d\n", offsetof(struct _ADAPTER, mlmeextpriv.TSFValue)); //+1992
+ printf("stapriv\t\t+%d\n", offsetof(struct _ADAPTER, stapriv)); //+3024 [164]
+ printf("pwrctrlpriv.bInternalAutoSuspend +%d\n", offsetof(struct _ADAPTER, pwrctrlpriv.bInternalAutoSuspend)); //+5061
+ printf("eeprompriv\t+%d\n", offsetof(struct _ADAPTER, eeprompriv)); // +5128
+ printf("HalData\t\t+%d\n", offsetof(struct _ADAPTER, HalData)); //+5656
+ printf("HalFunc\t\t+%d\n", offsetof(struct _ADAPTER, HalFunc)); //+5664
+ printf("bDriverStopped\t+%d\n", offsetof(struct _ADAPTER, bDriverStopped)); //+5880
+ printf("hw_init_completed +%d\n", offsetof(struct _ADAPTER, hw_init_completed)); //+5905
+ printf("stats\t\t+%d\n", offsetof(struct _ADAPTER, stats)); //+6024
+ printf("hw_init_mutex\t+%d\n", offsetof(struct _ADAPTER, hw_init_mutex)); //+6060
+ printf("fix_rate\t+%d\n", offsetof(struct _ADAPTER, fix_rate)); //+6084
+
+ printf("rltk_wlan_info = %p\n", &rltk_wlan_info);
+ dump_bytes((uint32_t)&rltk_wlan_info, sizeof(rltk_wlan_info));
+ _adapter * ad = *(_adapter **)((rltk_wlan_info[0].dev)->priv);
+ printf("adapter0 = %p, %p\n", ad, ad->pbuddy_adapter);
+ ad = *(_adapter **)((rltk_wlan_info[1].dev)->priv);
+ printf("adapter1 = %p, %p\n", ad, ad->pbuddy_adapter);
+ vTaskDelay(5);
+ dump_bytes((uint32_t)ad,sizeof(struct _ADAPTER));
+ vTaskDelay(5);
+
+ if (sizeof(struct _ADAPTER) != 6088) {
+ printf("Error: Check WiFi adapter struct!\n");
+ };
+}
+
+static void show_wlan_param(int argc, char *argv[]) {
+ (void)argc; (void)argv;
+ _adapter * ad = *(_adapter **)((rltk_wlan_info[0].dev)->priv);
+#if 1
+ printf("reconnect_deauth_filtered\t%u\n", ad->mlmeextpriv.reconnect_deauth_filtered);
+ printf("reconnect_times\t%u\n", ad->mlmeextpriv.reconnect_times);
+ printf("reconnect_cnt\t%u\n", ad->mlmeextpriv.reconnect_cnt);
+ printf("reconnect_timeout\t%u\n", ad->mlmeextpriv.reconnect_timeout);
+#endif
+
+}
+
+
+
+MON_RAM_TAB_SECTION COMMAND_TABLE console_wlan_tst[] = {
+ {"CHKWL", 0, tst_wlan_struct, ": Chk wlan struct"},
+ {"CHKAP", 0, show_wlan_param, ": Chow wlan parm"}
+};
diff --git a/RTLGDB/Project/driver/adc_drv.c b/RTLGDB/Project/driver/adc_drv.c
new file mode 100644
index 0000000..367a930
--- /dev/null
+++ b/RTLGDB/Project/driver/adc_drv.c
@@ -0,0 +1,196 @@
+/*
+ * Simple ADC DRV (adc_drv.c)
+ * Created on: 18 РёСЋРЅ. 2017 Рі.
+ * Author: pvvx
+ */
+
+#include
+
+#include "platform_autoconf.h"
+#include "diag.h"
+#include "rtl8195a_adc.h"
+#include "hal_adc.h"
+#include "driver/adc_drv.h"
+
+//------------------------------------------------------------------------------
+
+void ADCIrqInit(IRQ_FUN IrqFunc, uint32_t IrqData, uint32_t intr_enable)
+{
+ IRQ_HANDLE IrqHandle = {
+ .IrqNum = ADC_IRQ,
+ .Priority = 5
+ };
+ IrqHandle.Data = IrqData;
+ IrqHandle.IrqFun = IrqFunc;
+ InterruptRegister(&IrqHandle);
+ InterruptEn(&IrqHandle);
+ HAL_ADC_WRITE32(REG_ADC_INTR_EN, intr_enable);
+}
+
+void ADCIrqDeInit(void)
+{
+ IRQ_HANDLE IrqHandle = {
+ .IrqNum = ADC_IRQ,
+ .Priority = 5,
+ .Data = (uint32_t)NULL,
+ .IrqFun = (IRQ_FUN) NULL
+ };
+ HAL_ADC_WRITE32(REG_ADC_INTR_EN, 0);
+ InterruptUnRegister(&IrqHandle);
+}
+
+void ADCEnable(void)
+{
+ // Clear ADC Status
+ (void)HAL_ADC_READ32(REG_ADC_INTR_STS);
+ uint32_t AdcTempDat = HAL_ADC_READ32(REG_ADC_POWER);
+ AdcTempDat &= (~BIT_ADC_PWR_AUTO);
+ AdcTempDat |= 0x02;
+ HAL_ADC_WRITE32(REG_ADC_POWER, AdcTempDat);
+ AdcTempDat |= 0x04;
+ HAL_ADC_WRITE32(REG_ADC_POWER, AdcTempDat);
+ AdcTempDat &= (~0x08);
+ HAL_ADC_WRITE32(REG_ADC_POWER, AdcTempDat);
+
+ HAL_ADC_WRITE32(REG_ADC_ANAPAR_AD0, HAL_ADC_READ32(REG_ADC_ANAPAR_AD0) | BIT_ADC_EN_MANUAL);
+ HAL_ADC_WRITE32(REG_ADC_ANAPAR_AD1, HAL_ADC_READ32(REG_ADC_ANAPAR_AD1) | BIT_ADC_EN_MANUAL);
+}
+
+void ADCDisable(void)
+{
+#if ADC_USE_IRQ
+ HAL_ADC_WRITE32(REG_ADC_INTR_EN, 0);
+#endif
+
+ HAL_ADC_WRITE32(REG_ADC_ANAPAR_AD0, HAL_ADC_READ32(REG_ADC_ANAPAR_AD0) & (~BIT_ADC_EN_MANUAL));
+
+ HAL_ADC_WRITE32(REG_ADC_ANAPAR_AD1, HAL_ADC_READ32(REG_ADC_ANAPAR_AD1) & (~BIT_ADC_EN_MANUAL));
+
+ HAL_ADC_WRITE32(REG_ADC_POWER, HAL_ADC_READ32(REG_ADC_POWER) & (~(BIT_ADC_PWR_AUTO)));
+}
+
+#ifdef CONFIG_SOC_PS_MODULE
+static void ADCEnablePS(void)
+{
+ REG_POWER_STATE adcPwrState;
+ // To register a new peripheral device power state
+ adcPwrState.FuncIdx = ADC0;
+ adcPwrState.PwrState = ACT;
+ RegPowerState(adcPwrState);
+}
+#endif
+
+void ADCInit(ADC_MODULE_SEL adc_idx)
+{
+ // ADC Function and Clock Enable
+ // To release DAC delta sigma clock gating
+ HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_SYSPLL_CTRL2, HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_SYSPLL_CTRL2) | BIT25);
+ // Turn on DAC active clock
+ ACTCK_ADC_CCTRL(ON);
+ // Enable DAC0 module
+ ADC0_FCTRL(ON);
+ // Enable ADC power cut ?
+ // ADCEnablePW();
+ // ADC Control register set-up
+ HAL_ADC_WRITE32(REG_ADC_CONTROL,
+ BIT_CTRL_ADC_COMP_ONLY(ADC_FEATURE_DISABLED) // compare mode only enable (without FIFO enable)
+ | BIT_CTRL_ADC_ONESHOT(ADC_FEATURE_DISABLED) // one-shot mode enable
+ | BIT_CTRL_ADC_OVERWRITE(ADC_FEATURE_DISABLED) // overwrite mode enable
+ | BIT_CTRL_ADC_ENDIAN(ADC_DATA_ENDIAN_LITTLE) // endian selection
+ | BIT_CTRL_ADC_BURST_SIZE(8) // DMA operation threshold
+ | BIT_CTRL_ADC_THRESHOLD(8) // one shot mode threshold
+ | BIT_CTRL_ADC_DBG_SEL(ADC_DBG_SEL_DISABLE));
+#if 0
+ /* ADC compare value and compare method setting*/
+ switch (adc_idx)
+ {
+ case ADC0_SEL:
+ HAL_ADC_WRITE32(REG_ADC_COMP_VALUE_L,
+ (HAL_ADC_READ32(REG_ADC_COMP_VALUE_L)
+ & (~(BIT_ADC_COMP_TH_0(0xFFFF))))
+ | BIT_CTRL_ADC_COMP_TH_0(0) // ADC compare mode threshold
+ );
+ break;
+ case ADC1_SEL:
+ HAL_ADC_WRITE32(REG_ADC_COMP_VALUE_L,
+ (HAL_ADC_READ32(REG_ADC_COMP_VALUE_L)
+ & (~(BIT_ADC_COMP_TH_1(0xFFFF))))
+ | BIT_CTRL_ADC_COMP_TH_1(0) // ADC compare mode threshold
+ );
+ break;
+ case ADC2_SEL:
+ HAL_ADC_WRITE32(REG_ADC_COMP_VALUE_H,
+ (HAL_ADC_READ32(REG_ADC_COMP_VALUE_H)
+ & (~(BIT_ADC_COMP_TH_2(0xFFFF))))
+ | BIT_CTRL_ADC_COMP_TH_2(0) // ADC compare mode threshold
+ );
+ break;
+
+ case ADC3_SEL:
+ HAL_ADC_WRITE32(REG_ADC_COMP_VALUE_H,
+ (HAL_ADC_READ32(REG_ADC_COMP_VALUE_H)
+ & (~(BIT_ADC_COMP_TH_3(0xFFFF))))
+ | BIT_CTRL_ADC_COMP_TH_3(0) // ADC compare mode threshold
+ );
+ break;
+ }
+ /* ADC compare mode setting */
+ HAL_ADC_WRITE32(REG_ADC_COMP_SET,
+ HAL_ADC_READ32(REG_ADC_COMP_SET)
+ & (~(1 << adc_idx))); // compare mode control : less than the compare threshold
+#endif
+ // ADC audio mode set-up
+ // ADC enable manually setting
+ HAL_ADC_WRITE32(REG_ADC_ANAPAR_AD0, HAL_ADC_READ32(REG_ADC_ANAPAR_AD0)
+// & (~(BIT_ADC_AUDIO_EN)))
+// & (~(BIT_ADC_EN_MANUAL))
+ | BIT_ADC_AUDIO_EN // ADC audio mode enable
+ | BIT_ADC_EN_MANUAL // ADC enable manually
+ );
+ // ADC analog parameter 0
+ HAL_ADC_WRITE32(REG_ADC_ANAPAR_AD0, (HAL_ADC_READ32(REG_ADC_ANAPAR_AD0)
+// & (~BIT14) //ADC Input is internal?
+ | (BIT14))
+ & (~(BIT3|BIT2)));
+ // ADC analog parameter 1
+ HAL_ADC_WRITE32(REG_ADC_ANAPAR_AD1, (HAL_ADC_READ32(REG_ADC_ANAPAR_AD1) & (~BIT1)) | (BIT2|BIT0));
+ // ADC analog parameter 2
+ HAL_ADC_WRITE32(REG_ADC_ANAPAR_AD2, 0x67884400);
+ // ADC analog parameter 3
+ HAL_ADC_WRITE32(REG_ADC_ANAPAR_AD3, 0x77780039);
+ // ADC analog parameter 4
+ HAL_ADC_WRITE32(REG_ADC_ANAPAR_AD4, 0x0004d501);
+ // ADC analog parameter 5
+ HAL_ADC_WRITE32(REG_ADC_ANAPAR_AD5, 0x1E010800);
+#ifdef CONFIG_SOC_PS_MODULE
+ ADCEnablePS();
+#endif
+}
+
+void ADCDeInit(void)
+{
+#ifdef CONFIG_SOC_PS_MODULE
+ REG_POWER_STATE adcPwrState;
+ uint8_t HwState;
+ adcPwrState.FuncIdx = ADC0;
+ QueryRegPwrState(adcPwrState.FuncIdx, &(adcPwrState.PwrState), &HwState);
+ // if the power state isn't ACT, then switch the power state back to ACT first
+ if ((adcPwrState.PwrState != ACT) && (adcPwrState.PwrState != INACT))
+ {
+ ADCEnablePS();
+ QueryRegPwrState(adcPwrState.FuncIdx, &(adcPwrState.PwrState), &HwState);
+ }
+ if (adcPwrState.PwrState == ACT)
+ {
+ adcPwrState.PwrState = INACT;
+ RegPowerState(adcPwrState);
+ }
+#endif
+ // Turn on DAC active clock
+ ACTCK_ADC_CCTRL(OFF);
+ // Enable DAC1 module
+ ADC0_FCTRL(OFF);
+ // To release DAC delta sigma clock gating
+ HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_SYSPLL_CTRL2, HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_SYSPLL_CTRL2) & (~(BIT25)));
+}
+
diff --git a/RTLGDB/Project/driver/adc_drv.h b/RTLGDB/Project/driver/adc_drv.h
new file mode 100644
index 0000000..fe2c363
--- /dev/null
+++ b/RTLGDB/Project/driver/adc_drv.h
@@ -0,0 +1,23 @@
+/*
+ * Simple ADC DRV (adc_drv.h)
+ *
+ * Created on: 19 РёСЋРЅ. 2017 Рі.
+ * Author: pvvx
+ */
+
+#ifndef _DRIVER_ADC_DRV_H_
+#define _DRIVER_ADC_DRV_H_
+
+#include "rtl8195a.h"
+#include "rtl8195a_adc.h"
+
+void ADCIrqInit(IRQ_FUN IrqFunc, uint32_t IrqData, uint32_t intr_enable); // intr_enable = bits: REG_ADC_INTR_EN - BIT_ADC_FIFO_RD_ERROR_EN | BIT_ADC_FIFO_RD_REQ_EN | BIT_ADC_FIFO_FULL_EN ...
+void ADCIrqDeInit(void);
+
+void ADCInit(ADC_MODULE_SEL adc_idx); // RTL8711AM: adc_idx = ADC2_SEL = 2
+void ADCDeInit(void);
+void ADCEnable(void); // ADC Start
+void ADCDisable(void); // ADC Stop
+
+
+#endif /* _DRIVER_ADC_DRV_H_ */
diff --git a/RTLGDB/Project/driver/i2c_drv.c b/RTLGDB/Project/driver/i2c_drv.c
new file mode 100644
index 0000000..71c9de9
--- /dev/null
+++ b/RTLGDB/Project/driver/i2c_drv.c
@@ -0,0 +1,570 @@
+/*
+ * i2c_drv.c
+ *
+ * Created on: 02/05/2017.
+ * Author: pvvx
+ */
+#include "driver/i2c_drv.h"
+#include "rtl_lib.h"
+
+#if CONFIG_I2C_EN
+
+#include "pinmap.h"
+
+typedef struct {
+ unsigned char sda;
+ unsigned char scl;
+ unsigned char sel;
+ unsigned char id;
+} PinMapI2C;
+
+#define I2C_SEL(idx, ps) ((idx<<4) | ps)
+
+static const PinMapI2C PinMap_I2C[] = {
+ // sda, scl, sel, id
+ // I2C0
+ {PD_4, PD_5, I2C_SEL(0, S0), I2C0},
+ {PH_1, PH_0, I2C_SEL(0, S1), I2C0},
+ {PC_8, PC_9, I2C_SEL(0, S2), I2C0},
+ {PE_7, PE_6, I2C_SEL(0, S3), I2C0},
+ // I2C1
+ {PC_4, PC_5, I2C_SEL(1, S0), I2C1},
+ {PH_3, PH_2, I2C_SEL(1, S1), I2C1},
+ {PD_7, PD_6, I2C_SEL(1, S2), I2C1},
+ // I2C2
+ {PB_7, PB_6, I2C_SEL(2, S0), I2C2},
+ {PE_1, PE_0, I2C_SEL(2, S1), I2C2},
+ {PC_7, PC_6, I2C_SEL(2, S2), I2C2},
+ // I2C3
+ {PB_3, PB_2, I2C_SEL(3, S0), I2C3},
+ {PE_3, PE_2, I2C_SEL(3, S1), I2C3},
+ {PE_5, PE_4, I2C_SEL(3, S2), I2C3},
+ {PD_9, PD_8, I2C_SEL(3, S3), I2C3},
+
+ {0xff, 0xff, 0, 0}
+};
+
+static void * i2c_base_reg[4] = {
+ (void *)I2C0_REG_BASE,
+ (void *)I2C1_REG_BASE,
+ (void *)I2C2_REG_BASE,
+ (void *)I2C3_REG_BASE
+};
+
+#if 1
+#define test_printf(...)
+#define i2c_dump_regs(p)
+#else
+#define test_printf rtl_printf
+static int i2c_dump_regs(i2c_drv_t *pi2c)
+{
+ uint32 *ptr = pi2c->base_regs;
+ test_printf("%s:", __func__);
+ for(int i = 0; i < (0xA0>>2); i++) {
+ if(!(i%4)) {
+ test_printf("\n%08x:", &ptr[i]);
+ }
+ test_printf("\t%08x", ptr[i]);
+ }
+ test_printf("\n");
+}
+#endif
+
+#define i2c_reg(r) *((volatile uint32 *)(pi2c->base_regs + r))
+
+// flg =0 write, =1 Read
+static int i2c_ready(i2c_drv_t *pi2c, unsigned char flg)
+{
+ test_printf("%s:\n", __func__);
+ // Test enable i2c
+ if(!(i2c_reg(REG_DW_I2C_IC_ENABLE) & BIT_IC_ENABLE)) {
+ error_printf("I2C%d disable!\n", pi2c->idx);
+ pi2c->status = DRV_I2C_IC_OFF;
+ return DRV_I2C_IC_OFF;
+ }
+ // Wait Receive FIFO is empty & Transmit FIFO Completely Empty
+ int poll_count = DRV_I2C_POOL_TIMEOUT;
+ do {
+ if(i2c_reg(REG_DW_I2C_IC_RAW_INTR_STAT) & BIT_IC_RAW_INTR_STAT_TX_ABRT) {
+ error_printf("I2C%d Abort!\n", pi2c->idx);
+ // Clear abort status.
+ (volatile uint32)i2c_reg(REG_DW_I2C_IC_CLR_TX_ABRT);
+ // Be sure that all interrupts flag are cleared.
+// i2c_reg(REG_DW_I2C_IC_CLR_INTR);
+ pi2c->status = DRV_I2C_ABORT;
+ return DRV_I2C_ABORT;
+ }
+ if(flg) {
+ // Receive FIFO ready ?
+ if(i2c_reg(REG_DW_I2C_IC_STATUS) & (BIT_IC_STATUS_RFNE | BIT_IC_STATUS_RFF)) {
+ // pi2c->status = DRV_I2C_IC_ENABLE;
+ return DRV_I2C_OK;
+ }
+ }
+ else {
+ // Transmit FIFO is not full ?
+ if(i2c_reg(REG_DW_I2C_IC_STATUS) & BIT_IC_STATUS_TFNF) {
+ // pi2c->status = DRV_I2C_IC_ENABLE;
+ return DRV_I2C_OK;
+ }
+ }
+ } while(poll_count--);
+ error_printf("I2C%d Timeout!\n", pi2c->idx);
+ pi2c->status = DRV_I2C_TIMEOUT;
+ return DRV_I2C_TIMEOUT;
+}
+
+int _i2c_break(i2c_drv_t *pi2c)
+{
+ test_printf("%s\n", __func__);
+// i2c_reg(REG_DW_I2C_IC_CLR_INTR);
+ // ABORT operation
+ int poll_count = DRV_I2C_POOL_TIMEOUT;
+ i2c_reg(REG_DW_I2C_IC_ENABLE) |= 2;
+ // Wait until controller is disabled.
+ while(i2c_reg(REG_DW_I2C_IC_ENABLE) & 2) {
+ if(poll_count-- <= 0) {
+ error_printf("Error abort i2c%d\n", pi2c->idx);
+ pi2c->status = DRV_I2C_TIMEOUT;
+ return DRV_I2C_TIMEOUT;
+ };
+ };
+ pi2c->status = DRV_I2C_OFF;
+ // All interrupts flag are cleared.
+ (volatile uint32)i2c_reg(REG_DW_I2C_IC_CLR_INTR);
+ return DRV_I2C_OK;
+}
+
+/* (!) вызывать после _i2c_init */
+int _i2c_set_speed(i2c_drv_t *pi2c, uint32 clk_hz)
+{
+ test_printf("%s:\n", __func__);
+ if(clk_hz < 10000 || clk_hz > HalGetCpuClk()/16) {
+ error_printf("I2C%d Error clk!\n", pi2c->idx);
+ return DRV_I2C_ERR;
+ }
+ uint32 tmp;
+ uint32 CpuClkTmp = HalGetCpuClk()/clk_hz;
+ switch(pi2c->mode) {
+ case I2C_SS_MODE:
+ // Standard Speed Clock SCL High Count
+ tmp = (CpuClkTmp * I2C_SS_MIN_SCL_HTIME)/(I2C_SS_MIN_SCL_HTIME + I2C_SS_MIN_SCL_LTIME);
+ i2c_reg(REG_DW_I2C_IC_SS_SCL_HCNT) = BIT_CTRL_IC_SS_SCL_HCNT(tmp);
+ // Standard Speed Clock SCL Low Count
+ tmp = (CpuClkTmp * I2C_SS_MIN_SCL_LTIME)/(I2C_SS_MIN_SCL_HTIME + I2C_SS_MIN_SCL_LTIME);
+ i2c_reg(REG_DW_I2C_IC_SS_SCL_LCNT) = BIT_CTRL_IC_SS_SCL_LCNT(tmp);
+ break;
+ case I2C_HS_MODE:
+ // Standard Speed Clock SCL High Count
+ i2c_reg(REG_DW_I2C_IC_SS_SCL_HCNT) = BIT_CTRL_IC_SS_SCL_HCNT(400);
+ // Standard Speed Clock SCL Low Count
+ i2c_reg(REG_DW_I2C_IC_SS_SCL_LCNT) = BIT_CTRL_IC_SS_SCL_LCNT(470);
+ // Fast Speed Clock SCL High Count
+ i2c_reg(REG_DW_I2C_IC_FS_SCL_HCNT) = BIT_CTRL_IC_FS_SCL_HCNT(85);
+ // Fast Speed I2C Clock SCL Low Count
+ i2c_reg(REG_DW_I2C_IC_FS_SCL_LCNT) = BIT_CTRL_IC_FS_SCL_LCNT(105);
+ // High Speed I2C Clock SCL High Count
+ tmp = (CpuClkTmp * I2C_HS_MIN_SCL_HTIME_100)/(I2C_HS_MIN_SCL_HTIME_100 + I2C_HS_MIN_SCL_LTIME_100);
+ if (tmp > 8) tmp -= 3;
+ i2c_reg(REG_DW_I2C_IC_HS_SCL_HCNT) = BIT_CTRL_IC_HS_SCL_HCNT(tmp);
+ // High Speed I2C Clock SCL Low Count
+ tmp = (CpuClkTmp * I2C_HS_MIN_SCL_LTIME_100)/(I2C_HS_MIN_SCL_HTIME_100 + I2C_HS_MIN_SCL_LTIME_100);
+ if (tmp > 6) tmp -= 6;
+ i2c_reg(REG_DW_I2C_IC_HS_SCL_LCNT) = BIT_CTRL_IC_FS_SCL_LCNT(tmp);
+ break;
+// case I2C_FS_MODE:
+ default:
+ pi2c->mode = I2C_FS_MODE;
+ // Fast Speed Clock SCL High Count
+ tmp = (CpuClkTmp * I2C_FS_MIN_SCL_HTIME)/(I2C_FS_MIN_SCL_HTIME + I2C_FS_MIN_SCL_LTIME);
+ if (tmp > 4) tmp -= 4;// this part is according to the fine-tune result
+ i2c_reg(REG_DW_I2C_IC_FS_SCL_HCNT) = BIT_CTRL_IC_FS_SCL_HCNT(tmp);
+ // Fast Speed I2C Clock SCL Low Count
+ tmp = (CpuClkTmp * I2C_FS_MIN_SCL_LTIME)/(I2C_FS_MIN_SCL_HTIME + I2C_FS_MIN_SCL_LTIME);
+ if (tmp > 3) tmp -= 3; // this part is according to the fine-tune result
+ i2c_reg(REG_DW_I2C_IC_FS_SCL_LCNT) = BIT_CTRL_IC_FS_SCL_LCNT(tmp);
+ }
+ return DRV_I2C_OK;
+}
+
+static int i2c_disable(i2c_drv_t *pi2c)
+{
+ test_printf("%s:\n", __func__);
+ pi2c->status = DRV_I2C_IC_OFF;
+ if(i2c_reg(REG_DW_I2C_IC_ENABLE_STATUS) & BIT_IC_ENABLE_STATUS_IC_EN) {
+ test_printf("I2C%d Already disable!\n", pi2c->idx);
+ return DRV_I2C_OK;
+ }
+ // Disable controller.
+ int poll_count = DRV_I2C_POOL_TIMEOUT;
+ i2c_reg(REG_DW_I2C_IC_ENABLE) &= ~BIT_IC_ENABLE;
+ // Wait until controller is disabled.
+ while(i2c_reg(REG_DW_I2C_IC_ENABLE_STATUS) & BIT_IC_ENABLE_STATUS_IC_EN) {
+ if(poll_count-- <= 0) {
+ error_printf("I2C%d Error disable!\n", pi2c->idx);
+ pi2c->status = DRV_I2C_TIMEOUT;
+ return DRV_I2C_TIMEOUT;
+ };
+ };
+ return DRV_I2C_OK;
+}
+
+static int i2c_enable(i2c_drv_t *pi2c)
+{
+ test_printf("%s:\n", __func__);
+ int poll_count = DRV_I2C_POOL_TIMEOUT;
+ if(!(i2c_reg(REG_DW_I2C_IC_ENABLE_STATUS) & BIT_IC_ENABLE_STATUS_IC_EN)) {
+ // Enable controller.
+ i2c_reg(REG_DW_I2C_IC_ENABLE) = BIT_IC_ENABLE;
+ // Wait until controller is enabled
+ while(!(i2c_reg(REG_DW_I2C_IC_ENABLE_STATUS) & BIT_IC_ENABLE_STATUS_IC_EN)) {
+ if(poll_count-- <= 0) {
+ error_printf("I2C%d Error enable\n", pi2c->idx);
+ pi2c->status = DRV_I2C_TIMEOUT;
+ return DRV_I2C_TIMEOUT;
+ };
+ };
+ };
+ // Be sure that all interrupts flag are cleared.
+ (volatile uint32)i2c_reg(REG_DW_I2C_IC_CLR_INTR);
+ pi2c->status = DRV_I2C_IC_ENABLE;
+ return DRV_I2C_OK;
+}
+
+// IC On & Enable CLK
+static void _i2c_ic_on(i2c_drv_t *pi2c)
+{
+ test_printf("%s:\n", __func__);
+ uint32 tmp = 1 << (pi2c->idx << 1);
+ HAL_PERI_ON_WRITE32(REG_PESOC_PERI_CLK_CTRL1,
+ HAL_PERI_ON_READ32(REG_PESOC_PERI_CLK_CTRL1) | tmp);
+ HAL_PERI_ON_WRITE32(REG_PESOC_PERI_CLK_CTRL1,
+ HAL_PERI_ON_READ32(REG_PESOC_PERI_CLK_CTRL1) | (tmp << 1));
+ tmp = BIT_PERI_I2C0_EN << pi2c->idx;
+ HAL_PERI_ON_WRITE32(REG_SOC_PERI_FUNC0_EN,
+ HAL_PERI_ON_READ32(REG_SOC_PERI_FUNC0_EN) & (~tmp));
+ HAL_PERI_ON_WRITE32(REG_SOC_PERI_FUNC0_EN,
+ HAL_PERI_ON_READ32(REG_SOC_PERI_FUNC0_EN) | tmp);
+
+ tmp = HAL_READ32(PERI_ON_BASE, REG_PESOC_CLK_SEL);
+ tmp &= (~(BIT_PESOC_PERI_SCLK_SEL(3)));
+ HAL_WRITE32(PERI_ON_BASE, REG_PESOC_CLK_SEL, tmp);
+
+ HalPinCtrlRtl8195A(I2C0 + pi2c->idx, pi2c->io_sel, 1);
+}
+
+// IC Off & Disable CLK
+void _i2c_ic_off(i2c_drv_t *pi2c)
+{
+ test_printf("%s:\n", __func__);
+ if(pi2c->status) {
+ // mask all interrupts
+ i2c_reg(REG_DW_I2C_IC_INTR_MASK) = 0;
+ // Disable (Abort I2C Controller)
+ _i2c_break(pi2c);
+ i2c_disable(pi2c);
+ uint32 mask = BIT_PERI_I2C0_EN << pi2c->idx;
+ HAL_PERI_ON_WRITE32(REG_SOC_PERI_FUNC0_EN,
+ HAL_PERI_ON_READ32(REG_SOC_PERI_FUNC0_EN) & (~mask));
+ HalPinCtrlRtl8195A(I2C0 + pi2c->idx, pi2c->io_sel, 0);
+#ifdef CONFIG_SOC_PS_MODULE
+ REG_POWER_STATE i2cPwrState;
+ // To register a new peripheral device power state
+ i2cPwrState.FuncIdx = I2C0 + pi2c->idx;
+ i2cPwrState.PwrState = INACT;
+ RegPowerState(i2cPwrState);
+#endif
+ pi2c->status = DRV_I2C_OFF;
+ }
+}
+
+/* (!) вызывать до _i2c_init, если параметрв драйвера не заданы в i2c_drv_t */
+int _i2c_setup(i2c_drv_t *pi2c, PinName sda, PinName scl, unsigned char mode)
+{
+ test_printf("%s:\n", __func__);
+ if(mode < DRV_I2C_SS_MODE || mode > DRV_I2C_HS_MODE) {
+ error_printf("I2C Error mode!\n");
+ return DRV_I2C_ERR;
+ }
+ // Pins -> index
+ PinMapI2C *p = (PinMapI2C *)PinMap_I2C;
+ while(p->sda != 0xFF) {
+ if(p->sda == sda && p->scl == scl) {
+ pi2c->io_sel = RTL_GET_PERI_SEL(p->sel);
+ pi2c->idx = RTL_GET_PERI_IDX(p->sel);
+ pi2c->mode = mode;
+ return DRV_I2C_OK;
+ }
+ p++;
+ }
+ error_printf("I2C Error pins!\n");
+ return DRV_I2C_ERR;
+}
+
+/* (!) Рспользует заполненную структуру i2c_drv_t */
+int _i2c_init(i2c_drv_t *pi2c)
+{
+ test_printf("%s:\n", __func__);
+ // Set base address regs i2c
+ pi2c->base_regs = i2c_base_reg[pi2c->idx];
+ // IC On & Enable CLK
+ if(pi2c->status == DRV_I2C_OFF) _i2c_ic_on(pi2c);
+ // mask all interrupts
+ i2c_reg(REG_DW_I2C_IC_INTR_MASK) = 0;
+ // disable i2c
+ if(i2c_disable(pi2c)) return pi2c->status;
+ // Set Control Register:
+ // bit0: master enabled,
+ // bit1..2: fast mode (400 kbit/s), ...
+ // bit2: Slave Addressing Mode 7-bit
+ // bit4: Master Addressing Mode 7-bit
+ // bit5: Restart disable
+ // bit6: Slave Mode Disable
+ // bit7: STOP_DET_IFADDRESSED
+ // bit8: TX_EMPTY_CTRL
+ // bit9: RX_FIFO_FULL_HLD_CTRL
+ // Set MASTER_MODE
+ i2c_reg(REG_DW_I2C_IC_CON) =
+ BIT_CTRL_IC_CON_MASTER_MODE(1)
+ | BIT_IC_CON_SPEED(pi2c->mode)
+ | BIT_CTRL_IC_CON_IC_10BITADDR_SLAVE(0)
+ | BIT_CTRL_IC_CON_IC_10BITADDR_MASTER(0)
+ | BIT_CTRL_IC_CON_IC_RESTART_EN(1)
+ | BIT_CTRL_IC_CON_IC_SLAVE_DISABLE(1);
+ // Master Target Address
+ // i2c_reg(REG_DW_I2C_IC_TAR) = 0x40;
+ // Slave Address
+ // i2c_reg(REG_DW_I2C_IC_SAR) = 0x55;
+ // High Speed Master ID (00001xxx) bit0..2
+// i2c_reg(REG_DW_I2C_IC_HS_MADDR) = BIT_CTRL_IC_HS_MADDR(0x4);
+ // Standard Speed Clock SCL High Count (100kHz)
+ i2c_reg(REG_DW_I2C_IC_SS_SCL_HCNT) = BIT_CTRL_IC_SS_SCL_HCNT(400);
+ // Standard Speed Clock SCL Low Count (100kHz)
+ i2c_reg(REG_DW_I2C_IC_SS_SCL_LCNT) = BIT_CTRL_IC_SS_SCL_LCNT(470);
+ // Fast Speed Clock SCL High Count (400kHz)
+ i2c_reg(REG_DW_I2C_IC_FS_SCL_HCNT) = BIT_CTRL_IC_FS_SCL_HCNT(80);
+ // Fast Speed I2C Clock SCL Low Count (400kHz)
+ i2c_reg(REG_DW_I2C_IC_FS_SCL_LCNT) = BIT_CTRL_IC_FS_SCL_LCNT(100);
+ // High Speed I2C Clock SCL High Count (1MHz)
+ i2c_reg(REG_DW_I2C_IC_HS_SCL_HCNT) = BIT_CTRL_IC_HS_SCL_HCNT(30);
+ // High Speed I2C Clock SCL Low Count (1MHz)
+ i2c_reg(REG_DW_I2C_IC_HS_SCL_LCNT) = BIT_CTRL_IC_FS_SCL_LCNT(40);
+ // SDA Hold (IC_CLK period, when I2C controller acts as a transmitter/receiver)
+ i2c_reg(REG_DW_I2C_IC_SDA_HOLD) = BIT_CTRL_IC_SDA_HOLD(10);
+ // General Call Ack
+ i2c_reg(REG_DW_I2C_IC_ACK_GENERAL_CALL) = BIT_CTRL_IC_ACK_GENERAL_CALL(1);
+ // Receive FIFO Threshold Level
+ // i2c_reg(REG_DW_I2C_IC_RX_TL) = 0x0;
+ // Transmit FIFO Threshold Level
+ // i2c_reg(REG_DW_I2C_IC_TX_TL) = 0x0;
+ // Transmit Abort Source
+ // i2c_reg(REG_DW_I2C_IC_TX_ABRT_SOURCE) = 0x0;
+ // DMA Transmit Data Level Register
+ // i2c_reg(REG_DW_I2C_IC_DMA_TDLR) = 0x09;
+
+#ifdef CONFIG_SOC_PS_MODULE
+ REG_POWER_STATE i2cPwrState;
+ // To register a new peripheral device power state
+ i2cPwrState.FuncIdx = I2C0 + pi2c->idx;
+ i2cPwrState.PwrState = ACT;
+ RegPowerState(i2cPwrState);
+#endif
+ i2c_dump_regs(pi2c);
+// pi2c->status = DRV_I2C_IC_OFF;
+ return DRV_I2C_OK;
+}
+
+int _i2c_write(i2c_drv_t *pi2c, uint32 address, const char *data, int length, int stop)
+{
+ test_printf("%s: [%d]%d\n", __func__, length, stop);
+ uint8_t *d = (uint8_t *)data;
+ // Write slave address to TAR.
+ // bit12: = 1 - 10-bit addressing mode when acting as a master
+ // bit11: = 1 - Special Command Enable
+ // bit10: = 1 - Special Command Type START BYTE
+ i2c_reg(REG_DW_I2C_IC_TAR) = address;
+ // Enable controller
+ if(i2c_enable(pi2c)) return pi2c->status;
+ while (length--) {
+ // Transmit FIFO is not full
+ if(i2c_ready(pi2c, 0)) return pi2c->status; // BIT_IC_STATUS_TFNF
+ // Fill IC_DATA_CMD[7:0] with the data.
+ // Send stop after last byte ?
+ if(length == 0 && stop) i2c_reg(REG_DW_I2C_IC_DATA_CMD) = *d | BIT_IC_DATA_CMD_STOP;
+ else i2c_reg(REG_DW_I2C_IC_DATA_CMD) = *d;
+ d++;
+ }
+ // Disable controller.
+ if(stop) {
+ if(i2c_disable(pi2c)) return pi2c->status;
+ }
+ return DRV_I2C_OK;
+}
+
+int _i2c_read(i2c_drv_t *pi2c, uint32 address, const char *data, int length, int stop)
+{
+ test_printf("%s: [%d]%d\n", __func__, length, stop);
+ uint8_t *d = (uint8_t *)data;
+ int len = length;
+ // Write slave address to TAR.
+ // bit12: = 1 - 10-bit addressing mode when acting as a master
+ // bit11: = 1 - Special Command Enable
+ // bit10: = 1 - Special Command Type START BYTE
+ i2c_reg(REG_DW_I2C_IC_TAR) = address;
+ // Enable controller.
+ if(i2c_enable(pi2c)) return pi2c->status;
+ while (len--) {
+ // Transmit FIFO is not full
+ if(i2c_ready(pi2c, 0)) return pi2c->status; // BIT_IC_STATUS_TFE
+ // Send stop after last byte ?
+ if (len == 0 && stop) {
+ // bit10: = 1 - Restart Bit Control
+ // bit9: = 1 - Stop Bit Control
+ // bit8: = 1 - Command read / = 0 Command write
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD | BIT_IC_DATA_CMD_STOP;
+ } else {
+ // Read command -IC_DATA_CMD[8] = 1.
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD;
+ }
+ // Receive FIFO ready?
+ if(i2c_reg(REG_DW_I2C_IC_STATUS) & (BIT_IC_STATUS_RFNE | BIT_IC_STATUS_RFF)) {
+ // IC_DATA_CMD[7:0] contains received data.
+ if(length) {
+ *d++ = i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+ length--;
+ }
+ else (volatile uint32)i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+ };
+ }
+ while(length) {
+ // Receive FIFO ready?
+ if(i2c_ready(pi2c, 1)) return pi2c->status; // BIT_IC_STATUS_TFE
+ // IC_DATA_CMD[7:0] contains received data.
+ *d++ = i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+ length--;
+ };
+ // Disable controller.
+ if(stop) {
+ if(i2c_disable(pi2c)) return pi2c->status;
+ }
+ return DRV_I2C_OK;
+}
+
+#if defined(USE_I2C_CONSOLE) && USE_I2C_CONSOLE
+//extern void dump_bytes(uint32 addr, int size);
+extern int print_hex_dump(uint8_t *buf, int len, unsigned char k);
+extern uint32 hextoul(uint8 *s);
+
+i2c_drv_t ti2c;
+/* I2C Init:
+ * ati2c i [sda_pin [scl_pin [mode [speed]]]]
+ * I2C Deinit:
+ * ati2c d
+ * I2C Write:
+ * iati2c W address data1 [data2 ... [data8]...]
+ * I2C write + stop:
+ * iati2c w address data1 [data2 ... [data8]...]
+ * I2C Read:
+ * ati2c R address count
+ * I2C read + stop:
+ * ati2c r address count
+ */
+static void fATI2C(int argc, char *argv[])
+{
+ i2c_drv_t *pi2c = &ti2c;
+ uint8 buf[32];
+ if(argc > 1) {
+ if(argv[1][0] == 'i') {
+ //
+ if(!pi2c->status) {
+ uint8 sda = 0;
+ uint8 scl = 0;
+ uint8 mode = 0;
+ uint32 speed = 0;
+ if(argc > 2) sda = hextoul(argv[2]);
+ else if(argc > 3) scl = hextoul(argv[3]);
+ else if(argc > 4) mode = hextoul(argv[4]);
+ else if(argc > 5) speed = hextoul(argv[5]);
+ if(!sda) sda = PC_4;
+ if(!scl) scl = PC_5;
+ if(!mode) mode = DRV_I2C_FS_MODE;
+ if(!speed) speed = 50000;
+ if(_i2c_setup(pi2c, sda, scl, mode) == DRV_I2C_OK
+ && _i2c_init(pi2c) == DRV_I2C_OK
+ && _i2c_set_speed(pi2c, speed) == DRV_I2C_OK) {
+ rtl_printf("I2C%d Init: %02x %02x %02x %08x\n", pi2c->idx, sda, scl, mode, speed);
+ };
+ } else {
+ rtl_printf("Already init!\n");
+ return;
+ };
+ } else if(argv[1][0] == '?') {
+ rtl_printf("I2C Init:\n\tati2c i [sda_pin [scl_pin [mode [speed]]]]\n");
+ rtl_printf("I2C Deinit:\n\tati2c d\n");
+ rtl_printf("I2C Write:\n\tati2c W address data1 [data2 ... [data8]...]\n");
+ rtl_printf("I2C write + stop:\n\tati2c w address data1 [data2 ... [data8]...]\n");
+ rtl_printf("I2C Read:\n\tati2c R address count\n");
+ rtl_printf("I2C read + stop:\n\tati2c r address count\n");
+ rtl_printf("I2C get:\n\tati2c g address wrcount wrdata1 [..wrdata6] rdcount\n");
+ } else {
+ if(pi2c->status) {
+ if(argv[1][0] == 'd') {
+ _i2c_ic_off(pi2c);
+ rtl_printf("I2C%d DeInit\n", pi2c->idx);
+ return;
+ };
+ int i;
+ for(i = 0; i + 2 < argc; i++) {
+ buf[i] = hextoul(argv[i+2]);
+ };
+ if(i) {
+ if(argv[1][0] == 'w' || argv[1][0] == 'W') {
+ // >ati2c w 40 2
+ // I2C1 write[1]: 40 02 00
+ // I2C1 drvStatus = 1
+ _i2c_write(pi2c, buf[0], &buf[1], i-1, argv[1][0] == 'w');
+ rtl_printf("I2C%d write[%d]: ", pi2c->idx, i-1);
+ print_hex_dump(buf, i, ' ');
+ rtl_printf("\n");
+ } else if(argv[1][0] == 'r' || argv[1][0] == 'R') {
+ // >ati2c r 40 2
+ // I2C1 read[2]: 40 07 d8
+ // I2C1 drvStatus = 1
+ i = buf[1];
+ if(i > sizeof(buf) - 1) i = sizeof(buf) - 1;
+ _i2c_read(pi2c, buf[0], &buf[1], i, argv[1][0] == 'r');
+ rtl_printf("I2C%d read[%d]: ", pi2c->idx, i);
+ print_hex_dump(buf, i+1, ' ');
+ rtl_printf("\n");
+ } else if(argv[1][0] == 'g') {
+ // >ati2c g 5a 1 6 3
+ // I2C1 get[3]: 5a 5e 3a 6c
+ // I2C1 drvStatus = 1
+ if (argc < 5 || buf[1] == 0 || buf[1] > sizeof(buf) - 2) {
+ rtl_printf("Error command string!\n");
+ return;
+ }
+ if(_i2c_write(pi2c, buf[0], &buf[2], buf[1], 0) >= 0) {
+ i = buf[buf[1] + 2]; // кол-во байт чтения
+ if(i == 0 || i > sizeof(buf) - 1) i = sizeof(buf) - 1;
+ _i2c_read(pi2c, buf[0], &buf[1], i, 1);
+ rtl_printf("I2C%d get[%d]: ", pi2c->idx, i);
+ print_hex_dump(buf, i+1, ' ');
+ }
+ rtl_printf("\n");
+ };
+ };
+ };
+ };
+ };
+ rtl_printf("I2C%d Status = %d\n", pi2c->idx, pi2c->status);
+ return;
+}
+
+MON_RAM_TAB_SECTION COMMAND_TABLE console_commands_i2c[] = {
+ {"ATI2C", 0, fATI2C, ": Test I2C, nit, einit, rite, ead"},
+};
+#endif // USE_I2C_CONSOLE
+
+
+#endif // CONFIG_I2C_EN
diff --git a/RTLGDB/Project/driver/i2c_drv.h b/RTLGDB/Project/driver/i2c_drv.h
new file mode 100644
index 0000000..11d8405
--- /dev/null
+++ b/RTLGDB/Project/driver/i2c_drv.h
@@ -0,0 +1,55 @@
+/*
+ * i2c_drv.h
+ *
+ * Created on: 02/05/2017.
+ * Author: pvvx
+ */
+
+#ifndef PROJECT_INC_DRIVER_I2C_DRV_H_
+#define PROJECT_INC_DRIVER_I2C_DRV_H_
+
+#include "device.h"
+
+typedef struct _I2C_HND_ {
+ signed char status; // _i2c_status_e
+ unsigned char idx; // Номер контроллера I2C
+ unsigned char io_sel; // Location Index(Pin Mux Selection): S0 -> PC_4, PC_5
+ unsigned char mode; // _i2c_mode_e, if(I2C_FIXED_SPEED_MODE != 0) user set -> i2c_mode_e
+ void * base_regs;
+} i2c_drv_t, *i2c_drv_p;
+
+typedef enum
+{
+ DRV_I2C_OFF = 0, // IC I2C DeInit
+ DRV_I2C_OK = 0, // DRV ret Ok
+ DRV_I2C_IC_OFF = 1, // IC I2C Off
+ DRV_I2C_IC_ENABLE = 2, // IC I2C On
+ DRV_I2C_ERR = -1, // DRV ret err
+ DRV_I2C_ABORT = -1, // IC I2C Abort
+ DRV_I2C_TIMEOUT = -3 // IC I2C / DRV ret Timeout
+} _i2c_status_e;
+
+
+typedef enum
+{
+ DRV_I2C_SS_MODE = 1, // Standard Mode (100 Kbps)
+ DRV_I2C_FS_MODE = 2, // Fast Mode (400 Kbps)
+ DRV_I2C_HS_MODE = 3 // Fast Mode Plus (1 Mbps)
+} _i2c_mode_e;
+
+#define DRV_I2C_POOL_TIMEOUT 16384
+#define _i2c_deinit(p) _i2c_ic_off(p)
+
+// Setup
+int _i2c_setup(i2c_drv_t *pi2c, PinName sda, PinName scl, unsigned char mode); // _i2c_mode_e
+int _i2c_set_speed(i2c_drv_t *pi2c, uint32 clk_hz);
+// Work
+int _i2c_init(i2c_drv_t *pi2c);
+int _i2c_write(i2c_drv_t *pi2c, uint32 address, const char *data, int length, int stop);
+int _i2c_read(i2c_drv_t *pi2c, uint32 address, const char *data, int length, int stop);
+// Utils
+int _i2c_break(i2c_drv_t *pi2c);
+void _i2c_ic_off(i2c_drv_t *pi2c);
+
+
+#endif /* PROJECT_INC_DRIVER_I2C_DRV_H_ */
diff --git a/RTLGDB/Project/efuse_tst.c b/RTLGDB/Project/efuse_tst.c
new file mode 100644
index 0000000..703171f
--- /dev/null
+++ b/RTLGDB/Project/efuse_tst.c
@@ -0,0 +1,374 @@
+#include "efuse_tst.h"
+
+_LONG_CALL_ROM_ extern uint32_t HALEFUSEOneByteReadROM(IN uint32_t CtrlSetting, IN uint16_t Addr, OUT uint8_t *Data, IN uint8_t L25OutVoltage);
+_LONG_CALL_ROM_ extern uint32_t HALEFUSEOneByteWriteROM(IN uint32_t CtrlSetting, IN uint16_t Addr, IN uint8_t Data, IN uint8_t L25OutVoltage);
+
+
+//====================================================== Start libs
+//-----
+int _HalEFUSEPowerSwitch8195AROM(uint8_t bWrite, uint8_t PwrState, uint8_t L25OutVoltage)
+{
+ if (PwrState == 1)
+ {
+ HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_EEPROM_CTRL0, (HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_EEPROM_CTRL0) & 0xFFFFFF) | 0x69000000); // EFUSE_UNLOCK
+ if (!(HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_FUNC_EN) & BIT_SYS_FEN_EELDR)) // REG_SYS_FUNC_EN BIT_SYS_FEN_EELDR ?
+ HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_FUNC_EN, HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_FUNC_EN) | BIT_SYS_FEN_EELDR);
+ if (!(HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_CLK_CTRL0) & BIT_SYSON_CK_EELDR_EN)) // REG_SYS_CLK_CTRL0 BIT_SYSON_CK_EELDR_EN ?
+ HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_CLK_CTRL0, HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_CLK_CTRL0) | BIT_SYSON_CK_EELDR_EN);
+ if (!(HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_CLK_CTRL1) & BIT_PESOC_EELDR_CK_SEL)) // REG_SYS_CLK_CTRL1 BIT_PESOC_EELDR_CK_SEL ?
+ HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_CLK_CTRL1, HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_CLK_CTRL1) | BIT_PESOC_EELDR_CK_SEL);
+ if (bWrite == 1)
+ HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_REGU_CTRL0, (HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_REGU_CTRL0) & 0xFFFFF0FF) | BIT_SYS_REGU_LDO25E_EN | BIT_SYS_REGU_LDO25E_ADJ(L25OutVoltage));
+ }
+ else
+ {
+ HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_EEPROM_CTRL0, HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_EEPROM_CTRL0) & 0xFFFFFF); // EFUSE_UNLOCK
+ if ( bWrite == 1 )
+ HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_REGU_CTRL0, (HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_REGU_CTRL0) & (~BIT_SYS_REGU_LDO25E_EN)));
+ }
+ return bWrite;
+}
+
+//-----
+int _HALEFUSEOneByteReadROM(uint32_t CtrlSetting, uint16_t Addr, uint8_t *Data, uint8_t L25OutVoltage)
+{
+int i = 0, ret = 0;
+ if ( (Addr <= 0xFF) || ((CtrlSetting & 0xFFFF) == 0x26AE) )
+ {
+ _HalEFUSEPowerSwitch8195AROM(1, 1, L25OutVoltage);
+
+ HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_EFUSE_TEST, HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_EFUSE_TEST) & (~BIT_SYS_EF_FORCE_PGMEN));
+ HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_EFUSE_CTRL,
+ (CtrlSetting & (~(BIT_SYS_EF_RWFLAG | (BIT_MASK_SYS_EF_ADDR << BIT_SHIFT_SYS_EF_ADDR) | (BIT_MASK_SYS_EF_DATA << BIT_SHIFT_SYS_EF_DATA))))
+ | BIT_SYS_EF_ADDR(Addr));
+ if(HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_EFUSE_CTRL) & BIT_SYS_EF_RWFLAG)
+ {
+ *Data = HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_EFUSE_CTRL);
+ ret = 1;
+ }
+ else for(;;)
+ {
+ HalDelayUs(1000);
+ if(HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_EFUSE_CTRL) & BIT_SYS_EF_RWFLAG)
+ {
+ *Data = HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_EFUSE_CTRL);
+ ret = 1;
+ break;
+ }
+ if (i++ >= 100)
+ {
+ *Data = -1;
+ ret = 1;
+ break;
+ };
+ };
+ _HalEFUSEPowerSwitch8195AROM(1, 0, L25OutVoltage);
+ }
+ else *Data = -1;
+ return ret;
+}
+
+//-----
+int _HALOTPOneByteReadRAM(uint32_t CtrlSetting, int Addr, uint8_t *Data, uint8_t L25OutVoltage)
+{
+ int result;
+ if ( (unsigned int)(Addr - 128) > 0x1F )
+ result = 1;
+ else
+ result = _HALEFUSEOneByteReadROM(CtrlSetting, Addr, Data, L25OutVoltage);
+ return result;
+}
+
+//-----
+int _HALEFUSEOneByteReadRAM(uint32_t CtrlSetting, int Addr, uint8_t *Data, uint8_t L25OutVoltage)
+{
+ int result;
+
+ if ( (unsigned int)(Addr - 160) > 0x33 )
+ {
+ result = _HALEFUSEOneByteReadROM(CtrlSetting, Addr, Data, L25OutVoltage);
+ }
+ else
+ {
+ *Data = -1;
+ result = 1;
+ }
+ return result;
+}
+/*
+//-----
+void _ReadEOTPContant(uint8_t *pContant)
+{
+ int i;
+ for(i = 0; i < 32; i++ )
+ _HALOTPOneByteRead(HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_EFUSE_CTRL), i+128, &pContant[i], L25EOUTVOLTAGE);
+}
+*/
+//-----
+void _ReadEfuseContant(int UserCode, uint8_t *pContant)
+{
+#define EFUSE_SECTION 11
+ uint8_t *pbuf;
+ int eFuse_Addr;
+ int offset;
+ int bcnt;
+ int i, j;
+ uint8_t DataTemp0;
+ uint8_t DataTemp1;
+
+ pbuf = pContant;
+ eFuse_Addr = 0;
+ do
+ {
+ _HALEFUSEOneByteReadRAM(HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_EFUSE_CTRL), eFuse_Addr, &DataTemp0, L25EOUTVOLTAGE);
+ if ( DataTemp0 == 0x0FF ) break;
+ if ( (DataTemp0 & 0x0F) == 0x0F )
+ {
+ _HALEFUSEOneByteReadRAM(HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_EFUSE_CTRL), ++eFuse_Addr, &DataTemp1, L25EOUTVOLTAGE);
+ offset = ((DataTemp1 & 0x0F0) | (DataTemp0 >> 4)) >> 1;
+ bcnt = (~DataTemp1) & 0x0F;
+ if (((UserCode + EFUSE_SECTION) << 2) > offset || offset >= ((UserCode + EFUSE_SECTION + 1) << 2))
+ {
+ while (bcnt)
+ {
+ if (bcnt & 1) eFuse_Addr += 2;
+ bcnt >>= 1;
+ }
+ }
+ else
+ {
+ int base = (offset - ((EFUSE_SECTION + UserCode) << 2)) << 3;
+ j = 0;
+ while ( bcnt )
+ {
+ if ( bcnt & 1 )
+ {
+ _HALEFUSEOneByteReadRAM(HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_EFUSE_CTRL), ++eFuse_Addr, &pbuf[base + j], L25EOUTVOLTAGE);
+ _HALEFUSEOneByteReadRAM(HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_EFUSE_CTRL), ++eFuse_Addr, &pbuf[base + j + 1], L25EOUTVOLTAGE);
+ }
+ bcnt >>= 1;
+ j += 2;
+ }
+ }
+ }
+ else
+ {
+ for (i = (~DataTemp0) & 0x0F; i; i >>= 1 )
+ {
+ if (i & 1) eFuse_Addr += 2;
+ }
+ }
+ eFuse_Addr++;
+ }
+ while (eFuse_Addr <= 0x7E);
+}
+
+//-----
+void _ReadEfuseContant1(uint8_t *pContant)
+{
+ _ReadEfuseContant(0, pContant);
+}
+
+//-----
+void _ReadEfuseContant2(uint8_t *pContant)
+{
+ _ReadEfuseContant(1, pContant);
+}
+
+//-----
+void _ReadEfuseContant3(uint8_t *pContant)
+{
+ _ReadEfuseContant(2, pContant);
+}
+
+/*
+int _efuse_otp_read(uint8_t address, uint8_t len, uint8_t *buf)
+{
+ uint8_t content[32]; // the OTP max length is 32
+
+ if((address + len) > 32) return -1;
+ _ReadEOTPContant(content);
+ _memcpy(buf, content + address, len);
+ return 0;
+}
+*/
+//====================================================== end libs
+
+//======================================================
+// OTP : one time programming
+//======================================================
+
+uint8_t buf[128];
+
+#define OTP_MAX_LEN 32 // The OTP max length is 32 bytes
+static void efuse_otp_task(void *param)
+{
+ int ret;
+ uint8_t i;
+
+ DBG_8195A("\nefuse OTP block: Test Start\n");
+ // read OTP content
+ device_mutex_lock(RT_DEV_LOCK_EFUSE);
+ ret = efuse_otp_read(0, OTP_MAX_LEN, buf);
+ device_mutex_unlock(RT_DEV_LOCK_EFUSE);
+ if(ret < 0)
+ {
+ DBG_8195A("efuse OTP block: read address and length error\n");
+ goto exit;
+ }
+ for(i=0; i 0
+
+ ConfigDebugErr = -1; // ~_DBG_GDMA_;
+ ConfigDebugInfo = -1; // ~_DBG_GDMA_;
+ ConfigDebugWarn = -1; // ~_DBG_GDMA_;
+
+ DBG_8195A("EFUSE_CTRL=%08x\n", HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_EFUSE_CTRL));
+
+ if(xTaskCreate(fconf_read_task, ((const char*)"efuse_mtp_task"), 512, NULL, tskIDLE_PRIORITY + 1, NULL) != pdPASS)
+ printf("\n\r%s xTaskCreate(efuse_mtp_task) failed", __FUNCTION__);
+
+ if(xTaskCreate(efuse_otp_task, ((const char*)"efuse_otp_task"), 512, NULL, tskIDLE_PRIORITY + 2, NULL) != pdPASS)
+ printf("\n\r%s xTaskCreate(efuse_otp_task) failed", __FUNCTION__);
+
+ // Enable Schedule, Start Kernel
+ //if(rtw_get_scheduler_state() == OS_SCHEDULER_NOT_STARTED)
+ // vTaskStartScheduler();
+ //else
+ // vTaskDelete(NULL);
+
+ //for (;;) {}
+
+#endif
+}
diff --git a/RTLGDB/Project/efuse_tst.h b/RTLGDB/Project/efuse_tst.h
new file mode 100644
index 0000000..ae75ef9
--- /dev/null
+++ b/RTLGDB/Project/efuse_tst.h
@@ -0,0 +1,13 @@
+#include "FreeRTOS.h"
+#include "task.h"
+#include "diag.h"
+#include "hal_efuse.h"
+#include "efuse_api.h"
+#include "osdep_service.h"
+#include "device_lock.h"
+
+#define EFUSE_SHOW 1
+
+// https://esp8266.ru/forum/threads/calibration-data.1631/
+
+void efuse_main(void);
\ No newline at end of file
diff --git a/RTLGDB/Project/feep_config.h b/RTLGDB/Project/feep_config.h
new file mode 100644
index 0000000..2a8dc7d
--- /dev/null
+++ b/RTLGDB/Project/feep_config.h
@@ -0,0 +1,30 @@
+/*
+ * feep_config.h
+ *
+ * Created on: 06 РЅРѕСЏР±. 2016 Рі.
+ * Author: PVV
+ */
+
+#ifndef _INC_FEEP_CONFIG_H_
+#define _INC_FEEP_CONFIG_H_
+
+//#define FEEP_ID_WIFI_CFG 0x4347 // id:'0W', type: struct wlan_fast_reconnect
+//#define FEEP_ID_WIFI_AP_CFG 0x5041 // id:'1W', type: struct rtw_wifi_config_t
+#define FEEP_ID_UART_CFG 0x5530 // id:'0U', type: UART_LOG_CONF
+#define FEEP_ID_LWIP_CFG 0x4C30 // id:'0L', type: struct atcmd_lwip_conf
+#define FEEP_ID_DHCP_CFG 0x4430 // id:'0D', type: struct _sdhcp_cfg
+
+typedef struct _sdhcp_cfg {
+ uint8_t mode; // =0 dhcp off, =1 - dhcp on, =2 Static ip, =3 - auto
+ uint32_t ip;
+ uint32_t mask;
+ uint32_t gw;
+}dhcp_cfg;
+
+/*
+#define FEEP_WRITE_WIFI_CFG(x) flash_write_cfg(x, FEEP_ID_WIFI_CFG, sizeof(struct wlan_fast_reconnect))
+#define FEEP_READ_WIFI_CFG(x) flash_read_cfg(x, FEEP_ID_WIFI_CFG, sizeof(struct wlan_fast_reconnect))
+*/
+
+
+#endif /* _INC_FEEP_CONFIG_H_ */
diff --git a/RTLGDB/Project/flashconf_tst.c b/RTLGDB/Project/flashconf_tst.c
new file mode 100644
index 0000000..f5474d7
--- /dev/null
+++ b/RTLGDB/Project/flashconf_tst.c
@@ -0,0 +1,46 @@
+#include "flashconf_tst.h"
+
+#define FCONF_MAX_LEN 0x2000
+#define FCONF_ADDR_SHIFT 0x9000
+
+static void fconf_read_task(void *param)
+{
+ uint32_t i;
+ uint8_t buf[FCONF_MAX_LEN];
+ flash_t flash;
+
+ DBG_8195A("\nFlash conf block: Test Start\n");
+ _memset(buf, 0xFF, FCONF_MAX_LEN);
+ device_mutex_lock(RT_DEV_LOCK_FLASH);
+ flash_stream_read(&flash, FCONF_ADDR_SHIFT, FCONF_MAX_LEN, &buf);
+ device_mutex_unlock(RT_DEV_LOCK_FLASH);
+ for(i=0; i < FCONF_MAX_LEN; i+=8)
+ {
+ DBG_8195A("[%x]\t%02X %02X %02X %02X %02X %02X %02X %02X\n", i + FCONF_ADDR_SHIFT, buf[i], buf[i+1], buf[i+2], buf[i+3], buf[i+4], buf[i+5], buf[i+6], buf[i+7]);
+ }
+
+ DBG_8195A("Flash conf block: Test Done\n");
+ vTaskDelete(NULL);
+}
+
+void flashconf_main(void)
+{
+#if FLASHCONF_SHOW > 0
+
+ ConfigDebugErr = -1; // ~_DBG_GDMA_;
+ ConfigDebugInfo = -1; // ~_DBG_GDMA_;
+ ConfigDebugWarn = -1; // ~_DBG_GDMA_;
+
+ if(xTaskCreate(fconf_read_task, ((const char*)"fconf_read_task"), 512, NULL, tskIDLE_PRIORITY + 1, NULL) != pdPASS)
+ printf("\n\r%s xTaskCreate(fconf_read_task) failed", __FUNCTION__);
+
+ // Enable Schedule, Start Kernel
+ if(rtw_get_scheduler_state() == OS_SCHEDULER_NOT_STARTED)
+ vTaskStartScheduler();
+ else
+ vTaskDelete(NULL);
+
+ //for (;;) {}
+
+#endif
+}
diff --git a/RTLGDB/Project/flashconf_tst.h b/RTLGDB/Project/flashconf_tst.h
new file mode 100644
index 0000000..76dba86
--- /dev/null
+++ b/RTLGDB/Project/flashconf_tst.h
@@ -0,0 +1,11 @@
+#include "FreeRTOS.h"
+#include "task.h"
+#include "diag.h"
+#include "hal_efuse.h"
+#include "flash_api.h"
+#include "osdep_service.h"
+#include "device_lock.h"
+
+#define FLASHCONF_SHOW 1
+
+void flashconf_main(void);
\ No newline at end of file
diff --git a/RTLGDB/Project/ina219/ina219.h b/RTLGDB/Project/ina219/ina219.h
new file mode 100644
index 0000000..019b664
--- /dev/null
+++ b/RTLGDB/Project/ina219/ina219.h
@@ -0,0 +1,91 @@
+/**************************************************************************/
+/**************************************************************************/
+#ifndef _INA219_H_
+#define _INA219_H_
+
+/*=========================================================================
+ I2C ADDRESS/BITS
+ -----------------------------------------------------------------------*/
+ #define INA219_ADDRESS (0x80) // 1000000r (A0+A1=GND)
+ #define INA219_READ (0x01)
+/*=========================================================================*/
+
+/*=========================================================================
+ CONFIG REGISTER (R/W)
+ -----------------------------------------------------------------------*/
+ #define INA219_REG_CONFIG (0x00)
+ /*---------------------------------------------------------------------*/
+ #define INA219_CONFIG_RESET (0x8000) // Reset Bit
+
+ #define INA219_CONFIG_BVOLTAGERANGE_MASK (0x2000) // Bus Voltage Range Mask
+ #define INA219_CONFIG_BVOLTAGERANGE_16V (0x0000) // 0-16V Range
+ #define INA219_CONFIG_BVOLTAGERANGE_32V (0x2000) // 0-32V Range
+
+ #define INA219_CONFIG_GAIN_MASK (0x1800) // Gain Mask
+ #define INA219_CONFIG_GAIN_1_40MV (0x0000) // Gain 1, 40mV Range
+ #define INA219_CONFIG_GAIN_2_80MV (0x0800) // Gain 2, 80mV Range
+ #define INA219_CONFIG_GAIN_4_160MV (0x1000) // Gain 4, 160mV Range
+ #define INA219_CONFIG_GAIN_8_320MV (0x1800) // Gain 8, 320mV Range
+
+ #define INA219_CONFIG_BADCRES_MASK (0x0780) // Bus ADC Resolution Mask
+ #define INA219_CONFIG_BADCRES_9BIT (0x0080) // 9-bit bus res = 0..511
+ #define INA219_CONFIG_BADCRES_10BIT (0x0100) // 10-bit bus res = 0..1023
+ #define INA219_CONFIG_BADCRES_11BIT (0x0200) // 11-bit bus res = 0..2047
+ #define INA219_CONFIG_BADCRES_12BIT (0x0400) // 12-bit bus res = 0..4097
+
+ #define INA219_CONFIG_SADCRES_MASK (0x0078) // Shunt ADC Resolution and Averaging Mask
+ #define INA219_CONFIG_SADCRES_9BIT_1S_84US (0x0000) // 1 x 9-bit shunt sample
+ #define INA219_CONFIG_SADCRES_10BIT_1S_148US (0x0008) // 1 x 10-bit shunt sample
+ #define INA219_CONFIG_SADCRES_11BIT_1S_276US (0x0010) // 1 x 11-bit shunt sample
+ #define INA219_CONFIG_SADCRES_12BIT_1S_532US (0x0018) // 1 x 12-bit shunt sample
+ #define INA219_CONFIG_SADCRES_12BIT_1S_532US_ (0x0040) // 1 x 12-bit shunt sample
+ #define INA219_CONFIG_SADCRES_12BIT_2S_1060US (0x0048) // 2 x 12-bit shunt samples averaged together
+ #define INA219_CONFIG_SADCRES_12BIT_4S_2130US (0x0050) // 4 x 12-bit shunt samples averaged together
+ #define INA219_CONFIG_SADCRES_12BIT_8S_4260US (0x0058) // 8 x 12-bit shunt samples averaged together
+ #define INA219_CONFIG_SADCRES_12BIT_16S_8510US (0x0060) // 16 x 12-bit shunt samples averaged together
+ #define INA219_CONFIG_SADCRES_12BIT_32S_17MS (0x0068) // 32 x 12-bit shunt samples averaged together
+ #define INA219_CONFIG_SADCRES_12BIT_64S_34MS (0x0070) // 64 x 12-bit shunt samples averaged together
+ #define INA219_CONFIG_SADCRES_12BIT_128S_69MS (0x0078) // 128 x 12-bit shunt samples averaged together
+
+ #define INA219_CONFIG_MODE_MASK (0x0007) // Operating Mode Mask
+ #define INA219_CONFIG_MODE_POWERDOWN (0x0000)
+ #define INA219_CONFIG_MODE_SVOLT_TRIGGERED (0x0001)
+ #define INA219_CONFIG_MODE_BVOLT_TRIGGERED (0x0002)
+ #define INA219_CONFIG_MODE_SANDBVOLT_TRIGGERED (0x0003)
+ #define INA219_CONFIG_MODE_ADCOFF (0x0004)
+ #define INA219_CONFIG_MODE_SVOLT_CONTINUOUS (0x0005)
+ #define INA219_CONFIG_MODE_BVOLT_CONTINUOUS (0x0006)
+ #define INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS (0x0007)
+/*=========================================================================*/
+
+/*=========================================================================
+ SHUNT VOLTAGE REGISTER (R)
+ -----------------------------------------------------------------------*/
+ #define INA219_REG_SHUNTVOLTAGE (0x01)
+/*=========================================================================*/
+
+/*=========================================================================
+ BUS VOLTAGE REGISTER (R)
+ -----------------------------------------------------------------------*/
+ #define INA219_REG_BUSVOLTAGE (0x02)
+/*=========================================================================*/
+
+/*=========================================================================
+ POWER REGISTER (R)
+ -----------------------------------------------------------------------*/
+ #define INA219_REG_POWER (0x03)
+/*=========================================================================*/
+
+/*=========================================================================
+ CURRENT REGISTER (R)
+ -----------------------------------------------------------------------*/
+ #define INA219_REG_CURRENT (0x04)
+/*=========================================================================*/
+
+/*=========================================================================
+ CALIBRATION REGISTER (R/W)
+ -----------------------------------------------------------------------*/
+ #define INA219_REG_CALIBRATION (0x05)
+/*=========================================================================*/
+
+#endif // _INA219_H_
diff --git a/RTLGDB/Project/ina219/ina219buf.c b/RTLGDB/Project/ina219/ina219buf.c
new file mode 100644
index 0000000..129f6c0
--- /dev/null
+++ b/RTLGDB/Project/ina219/ina219buf.c
@@ -0,0 +1,275 @@
+/*
+ * ina219buf.c
+ *
+ * Created on: 02/05/2017
+ * Author: pvvx
+ */
+#include
+#include "rtl8195a.h"
+#include "device.h"
+#include "PinNames.h"
+
+#include "basic_types.h"
+#include "diag.h"
+#include "osdep_api.h"
+
+//#include "i2c_api.h"
+//#include "i2c_ex_api.h"
+#include "pinmap.h"
+#include "rtl_lib.h"
+#include "ina219/ina219buf.h"
+#include "rtl8195a/rtl_libc.h"
+#include "driver/i2c_drv.h"
+
+INA219DRV ina219drv = {
+ .addr = INA219_ADDRESS>>1,
+ .config =
+ INA219_CONFIG_BVOLTAGERANGE_16V | // INA219_CONFIG_BVOLTAGERANGE_32V
+ INA219_CONFIG_GAIN_8_320MV | // INA219_CONFIG_GAIN_1_40MV |
+ INA219_CONFIG_BADCRES_12BIT |
+ INA219_CONFIG_SADCRES_12BIT_2S_1060US | // INA219_CONFIG_SADCRES_12BIT_128S_69MS |
+ INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS,
+ .calibration = 8192,
+ .i2c.status = DRV_I2C_OFF,
+ .i2c.idx = 1, // I2C1
+ .i2c.io_sel = S0, // PC_4, PC_5
+ .i2c.mode = DRV_I2C_FS_MODE // DRV_I2C_HS_MODE
+};
+
+void ina219_write(unsigned char reg, unsigned short data)
+{
+ PINA219DRV p = &ina219drv;
+ p->buf_i2c.uc[0] = reg;
+ p->buf_i2c.uc[1] = (unsigned char)((unsigned short)(data >> 8));
+ p->buf_i2c.uc[2] = (unsigned char)data;
+ _i2c_write(&p->i2c, p->addr, (const char *)p->buf_i2c.uc, 3, 1);
+}
+
+unsigned int ina219_read(unsigned char reg)
+{
+ PINA219DRV p = &ina219drv;
+ p->buf_i2c.uc[0] = reg;
+ _i2c_write(&p->i2c, p->addr, (const char *)p->buf_i2c.uc, 1, 1);
+ p->buf_i2c.ui = 0;
+ _i2c_read(&p->i2c, p->addr, (const char *)p->buf_i2c.uc, 2, 1);
+ return (p->buf_i2c.uc[0] << 8) | p->buf_i2c.uc[1];
+}
+
+#define i2c_reg(r) *((volatile uint32 *)(pi2c->base_regs + r))
+
+/* Пример непрерывного чтения регистров
+ * тока и напряжения IN219 по прерыванию таймера */
+void ina_tick_handler(void *par) {
+ PINA219DRV p = &ina219drv;
+ i2c_drv_t *pi2c = &p->i2c;
+ switch(p->status) {
+ default:
+ // Disable controller.
+ i2c_reg(REG_DW_I2C_IC_ENABLE) = 0;
+ p->status = 1;
+ break;
+ case 1:
+ // Master Target Address
+ i2c_reg(REG_DW_I2C_IC_TAR) = p->addr;
+ // Enable controller.
+ i2c_reg(REG_DW_I2C_IC_ENABLE) = BIT_IC_ENABLE;
+ p->status = 2;
+ break;
+ case 2:
+ // Заполним FIFO ic I2C командами инициализации INA219
+ // Write addr reg.
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = INA219_REG_CONFIG;
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = p->config >> 8;
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = (p->config & 0x0FF) | BIT_IC_DATA_CMD_STOP;
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = INA219_REG_CALIBRATION;
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = p->calibration >> 8;
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = (p->calibration & 0x0FF) | BIT_IC_DATA_CMD_STOP;
+ //
+ p->status = 3;
+ break;
+ case 4:
+ if (i2c_reg(REG_DW_I2C_IC_RAW_INTR_STAT) & BIT_IC_RAW_INTR_STAT_TX_ABRT) {
+ uint32 tmp = i2c_reg(REG_DW_I2C_IC_CLR_INTR);
+ p->errs++;
+ p->status = 0;
+ break;
+ } else {
+ // Считаем готовые значения из FIFO ic I2C
+ p->buf_i2c.uc[1] = i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+ p->buf_i2c.uc[0] = i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+ p->buf_i2c.uc[3] = i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+ p->buf_i2c.uc[2] = i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+ p->count++;
+ }
+ case 3:
+ // Заполним FIFO ic I2C командами чтения
+ // Write addr reg.
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = INA219_REG_BUSVOLTAGE | BIT_IC_DATA_CMD_STOP;
+ // Read command.
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD;
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD | BIT_IC_DATA_CMD_STOP;
+ // Write addr reg.
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = INA219_REG_SHUNTVOLTAGE | BIT_IC_DATA_CMD_STOP;
+ // Read command.
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD;
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD | BIT_IC_DATA_CMD_STOP;
+ p->status = 4;
+ break;
+ }
+}
+
+void ina219_init(void)
+{
+ PINA219DRV p = &ina219drv;
+ if(p->init <= 0) {
+ rtl_printf("Init INA219\n");
+ p->status = 0;
+ p->count = 0;
+ p->errs = 0;
+// (!) Установки драйвера I2C заданы в структуре ina219drv
+// rtl_printf("INA219 control reg = 0x%04x\n", p->config);
+// _i2c_setup(&p->i2c, INA219_I2C_PIN_SDA , INA219_I2C_PIN_SCL, DRV_I2C_FS_MODE); // == DRV_I2C_OK?
+ _i2c_init(&p->i2c);
+// _i2c_set_speed(&p->i2c, INA219_I2C_BUS_CLK);
+ rtl_printf("I2C%d mode = %d, drvStatus = %d\n", p->i2c.idx, p->i2c.mode, p->i2c.status);
+// (!) Рнициализация INA219 перенесена РІ прерывание таймера
+// ina219_write(INA219_REG_CONFIG, p->config);
+// ina219_write(INA219_REG_CALIBRATION, p->calibration);
+ // Initial a periodical timer
+ gtimer_init(&p->timer, INA219_TIMER);
+ // Tick every 0.000532 sec (N*532 Ојs)
+ uint32 tus = 1 << ((p->config >> 3) & 7);
+ tus *= 532;
+ rtl_printf("INA219 Read Period = %u us\n", tus);
+ gtimer_start_periodical(&p->timer, tus, (void*)ina_tick_handler, (uint32_t)&ina219drv);
+ p->init = 1;
+ }
+}
+
+void ina219_deinit(void)
+{
+ PINA219DRV p = &ina219drv;
+ i2c_drv_t *pi2c = &p->i2c;
+ if(p->init > 0) {
+ rtl_printf("Deinit INA219\n");
+ gtimer_stop(&p->timer);
+ gtimer_deinit(&p->timer);
+// (!) Не используется ina219_write / ina219_read для сокращения кода
+// ina219_write(INA219_REG_CONFIG, INA219_CONFIG_MODE_POWERDOWN);
+ // Break controller.
+ i2c_reg(REG_DW_I2C_IC_ENABLE) |= 2;
+ vTaskDelay(2); // +WDT
+ // Disable controller.
+ i2c_reg(REG_DW_I2C_IC_ENABLE) = 0;
+ vTaskDelay(2); // +WDT
+ // Master Target Address
+ i2c_reg(REG_DW_I2C_IC_TAR) = p->addr;
+ // Enable controller.
+ i2c_reg(REG_DW_I2C_IC_ENABLE) = BIT_IC_ENABLE;
+ // Заполним FIFO ic I2C командой отключения INA219
+ vTaskDelay(2); // +WDT
+ // Write addr reg. INA219 POWER_DOWN
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = INA219_REG_CONFIG;
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = (INA219_CONFIG_MODE_POWERDOWN >> 8);
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = (INA219_CONFIG_MODE_POWERDOWN & 0x0F) | BIT_IC_DATA_CMD_STOP;
+ vTaskDelay(2); // +WDT
+ _i2c_deinit(&p->i2c);
+ }
+ p->init = -1;
+}
+
+static void ShowIna(void)
+{
+ PINA219DRV p = &ina219drv;
+ rtl_printf("INA219: %d, %d\n", p->buf_i2c.us[0], p->buf_i2c.ss[1]);
+ rtl_printf("INA219: Cnt = %u, Err = %u\n", p->count, p->errs);
+}
+
+static void fATINA(int argc, char *argv[])
+{
+ if(argc > 1) {
+ if(atoi(argv[1])) {
+ ina219_init();
+ vTaskDelay(10); // +WDT
+ }
+ else ina219_deinit();
+ }
+ ShowIna();
+}
+
+
+extern void dump_bytes(uint32 addr, int size);
+extern uint32 hextoul(uint8 *s);
+
+i2c_drv_t ti2c;
+/* Sample:
+ * ati2c i
+ * ati2c w 40 5
+ * ati2c r 40 2
+ */
+static void fATI2C(int argc, char *argv[])
+{
+ i2c_drv_t *pi2c = &ti2c;
+ uint8 buf[32];
+ if(argc > 1) {
+ if(argv[1][0] == 'i') {
+ if(!pi2c->status) {
+ uint8 sda = 0;
+ uint8 scl = 0;
+ uint8 mode = 0;
+ uint32 speed = 0;
+ if(argc > 2) sda = hextoul(argv[2]);
+ else if(argc > 3) scl = hextoul(argv[3]);
+ else if(argc > 4) mode = hextoul(argv[4]);
+ else if(argc > 5) speed = hextoul(argv[5]);
+ if(!sda) sda = PC_4;
+ if(!scl) scl = PC_5;
+ if(!mode) mode = DRV_I2C_FS_MODE;
+ if(!speed) speed = 400000;
+ if(_i2c_setup(pi2c, sda, scl, mode) == DRV_I2C_OK
+ && _i2c_init(pi2c) == DRV_I2C_OK
+ && _i2c_set_speed(pi2c, speed) == DRV_I2C_OK) {
+ rtl_printf("I2C%d Init\n", pi2c->idx);
+ };
+ } else {
+ rtl_printf("Already init!\n");
+ return;
+ };
+ } else {
+ if(pi2c->status) {
+ if(argv[1][0] == 'd') {
+ _i2c_ic_off(pi2c);
+ rtl_printf("I2C%d DeInit\n", pi2c->idx);
+ return;
+ };
+ int i;
+ for(i = 0; i + 2 < argc; i++) {
+ buf[i] = hextoul(argv[i+2]);
+ };
+ if(i) {
+ if(argv[1][0] == 'w') {
+ _i2c_write(pi2c, buf[0], &buf[1], i-1, 1);
+ rtl_printf("I2C%d write[%d]:\n", pi2c->idx, i-1);
+ dump_bytes(&buf[0], i);
+ }
+ else if(argv[1][0] == 'r') {
+ i = buf[1];
+ if(i > sizeof(buf) - 1) i = sizeof(buf) - 1;
+ _i2c_read(pi2c, buf[0], &buf[1], i, 1);
+ rtl_printf("I2C%d read[%d]:\n", pi2c->idx, i);
+ dump_bytes(&buf[0], i+1);
+ };
+
+ };
+ };
+ };
+ };
+ rtl_printf("I2C%d drvStatus = %d\n", pi2c->idx, pi2c->status);
+ return;
+}
+
+MON_RAM_TAB_SECTION COMMAND_TABLE console_commands_ina219[] = {
+ {"ATI2C", 0, fATI2C, ": Test I2C, nit, einit, rite, ead"},
+ {"ATINA", 0, fATINA, "=[0/1]: INA219 =1 start, =0 stop"}
+};
+
diff --git a/RTLGDB/Project/ina219/ina219buf.h b/RTLGDB/Project/ina219/ina219buf.h
new file mode 100644
index 0000000..67e2b0e
--- /dev/null
+++ b/RTLGDB/Project/ina219/ina219buf.h
@@ -0,0 +1,43 @@
+/**************************************************************************
+ * Драйвер для INA219
+ **************************************************************************/
+#ifndef _INA219DRV_H_
+#define _INA219DRV_H_
+#include "ina219/ina219.h"
+#include "device.h"
+#include "timer_api.h"
+#include "driver/i2c_drv.h"
+
+typedef struct _ina219data {
+ signed short voltage; // Voltage, 1mV
+ signed short current; // Current, 50uA?
+ signed short power; // Power, 1mW
+ unsigned short shunt; // 10uV
+} INA219DATA, *PINA219DATA;
+
+typedef struct _ina219drv {
+ unsigned char status;
+ unsigned char addr;
+ signed char init;
+ unsigned char tmp;
+ unsigned short config; // регистр конфигурации INA219
+ unsigned short calibration; // коэф. шунта для INA219
+ unsigned int count;
+ unsigned int errs;
+ gtimer_t timer;
+ union { // буфер
+ unsigned char uc[4];
+ unsigned short us[2];
+ signed short ss[2];
+ unsigned int ui;
+ } buf_i2c;
+ i2c_drv_t i2c;
+} INA219DRV, *PINA219DRV;
+
+
+#define INA219_I2C_PIN_SDA PC_4
+#define INA219_I2C_PIN_SCL PC_5
+#define INA219_I2C_BUS_CLK 300000 //hz
+#define INA219_TIMER TIMER3 // используемый таймер
+
+#endif // _INA219DRV_H_
diff --git a/RTLGDB/Project/ina219/ina219drv.c b/RTLGDB/Project/ina219/ina219drv.c
new file mode 100644
index 0000000..796c183
--- /dev/null
+++ b/RTLGDB/Project/ina219/ina219drv.c
@@ -0,0 +1,347 @@
+/*
+ * ina219drv.c
+ *
+ * Created on: 02/05/2017
+ * Author: pvvx
+ */
+#include
+#include "rtl8195a.h"
+#include "device.h"
+#include "PinNames.h"
+
+#include "basic_types.h"
+#include "diag.h"
+#include "osdep_api.h"
+
+//#include "i2c_api.h"
+//#include "i2c_ex_api.h"
+#include "pinmap.h"
+#include "rtl_lib.h"
+#include "ina219/ina219drv.h"
+#include "rtl8195a/rtl_libc.h"
+#include "driver/i2c_drv.h"
+#include "platform_stdlib.h"
+#include "web_websocket.h"
+#include "tcpsrv/tcp_srv_conn.h"
+
+#include "hal_com_reg.h"
+
+//#define ReadTSF_Lo32() (*((volatile unsigned int *)(WIFI_REG_BASE + REG_TSFTR)))
+//#define ReadTSF_Hi32() (*((volatile unsigned int *)(WIFI_REG_BASE + REG_TSFTR1)))
+
+INA219DRV ina219drv = {
+ .addr = INA219_ADDRESS>>1,
+ .config =
+ INA219_CONFIG_BVOLTAGERANGE_16V | // INA219_CONFIG_BVOLTAGERANGE_32V
+ INA219_CONFIG_GAIN_8_320MV | // INA219_CONFIG_GAIN_1_40MV |
+ INA219_CONFIG_BADCRES_12BIT |
+ INA219_CONFIG_SADCRES_12BIT_1S_532US | //INA219_CONFIG_SADCRES_12BIT_2S_1060US | // INA219_CONFIG_SADCRES_12BIT_1S_532US | //
+ INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS,
+ .calibration = 8192, // при шунте 0.1 Ом
+ .buf_idx = 709, // циклический буфер на 710 замеров (по 4 байт -> sizeof(INA219DATA))
+ // Если шаг заполнения 1 ms -> буфер на 0.71 сек
+ // Оптимизация под TCP: (TCP_MSS*2 - 80)/4 = (1460*2 - 80)/4 = 710
+ .i2c.status = DRV_I2C_OFF,
+ .i2c.idx = 1, // I2C1
+ .i2c.io_sel = S0, // PC_4, PC_5
+ .i2c.mode = DRV_I2C_FS_MODE // DRV_I2C_HS_MODE
+};
+/*
+void ina219_write(unsigned char reg, unsigned short data)
+{
+ PINA219DRV p = &ina219drv;
+ p->buf_i2c.uc[0] = reg;
+ p->buf_i2c.uc[1] = (unsigned char)((unsigned short)(data >> 8));
+ p->buf_i2c.uc[2] = (unsigned char)data;
+ _i2c_write(&p->i2c, p->addr, (const char *)p->buf_i2c.uc, 3, 1);
+ UBaseType_t f;
+ portBASE_TYPE d;
+}
+
+unsigned int ina219_read(unsigned char reg)
+{
+ PINA219DRV p = &ina219drv;
+ p->buf_i2c.uc[0] = reg;
+ _i2c_write(&p->i2c, p->addr, (const char *)p->buf_i2c.uc, 1, 1);
+ p->buf_i2c.ui = 0;
+ _i2c_read(&p->i2c, p->addr, (const char *)p->buf_i2c.uc, 2, 1);
+ return (p->buf_i2c.uc[0] << 8) | p->buf_i2c.uc[1];
+}
+*/
+
+#define i2c_reg(r) *((volatile uint32 *)(pi2c->base_regs + r))
+
+/* Пример непрерывного чтения регистров
+ * тока и напряжения IN219 по прерыванию таймера */
+void ina_tick_handler(void *par) {
+ PINA219DRV p = &ina219drv;
+ i2c_drv_t *pi2c = &p->i2c;
+ switch(p->status) {
+ default:
+ // Disable controller.
+ i2c_reg(REG_DW_I2C_IC_ENABLE) = 0;
+ p->status = 1;
+ break;
+ case 1:
+ // Master Target Address
+ i2c_reg(REG_DW_I2C_IC_TAR) = p->addr;
+ // Enable controller.
+ i2c_reg(REG_DW_I2C_IC_ENABLE) = BIT_IC_ENABLE;
+ p->status = 2;
+ break;
+ case 2:
+ // Заполним FIFO ic I2C командами инициализации INA219
+ // Write addr reg.
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = INA219_REG_CONFIG;
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = p->config >> 8;
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = (p->config & 0x0FF) | BIT_IC_DATA_CMD_STOP;
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = INA219_REG_CALIBRATION;
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = p->calibration >> 8;
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = (p->calibration & 0x0FF) | BIT_IC_DATA_CMD_STOP;
+ //
+ p->status = 3;
+ break;
+ case 4:
+ if (i2c_reg(REG_DW_I2C_IC_RAW_INTR_STAT) & BIT_IC_RAW_INTR_STAT_TX_ABRT) {
+ (volatile uint32)i2c_reg(REG_DW_I2C_IC_CLR_INTR);
+ p->errs++;
+ p->status = 0;
+ break;
+ } else {
+ if(p->pbuf) {
+ PINA219DATA pd = p->pbuf + p->buf_tx;
+ // Считаем готовые значения из FIFO ic I2C
+ pd->v.vuc[1] = i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+ pd->v.vuc[0] = i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+ pd->i.iuc[1] = i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+ pd->i.iuc[0] = i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+ if(p->buf_tx >= p->buf_idx) p->buf_tx = 0;
+ else p->buf_tx++;
+ if(p->buf_rx == p->buf_tx) {
+ p->overrun++; // todo: if(p->overrun++ > 100000) deinit() ?
+ if(p->buf_rx >= p->buf_idx) p->buf_rx = 0;
+ else p->buf_rx++;
+ };
+ } else {
+ (volatile uint32)i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+ (volatile uint32)i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+ (volatile uint32)i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+ (volatile uint32)i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+ };
+ }
+ case 3:
+ // Заполним FIFO ic I2C командами чтения
+ // Write addr reg.
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = INA219_REG_BUSVOLTAGE | BIT_IC_DATA_CMD_STOP;
+ // Read command.
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD;
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD | BIT_IC_DATA_CMD_STOP;
+ // Write addr reg.
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = INA219_REG_SHUNTVOLTAGE | BIT_IC_DATA_CMD_STOP;
+ // Read command.
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD;
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD | BIT_IC_DATA_CMD_STOP;
+ p->status = 4;
+ break;
+ }
+}
+
+uint16 ina219_chkdata(uint16 cnt)
+{
+ PINA219DRV p = &ina219drv;
+ if(p->init <= 0) return 0;
+ int len = p->buf_tx - p->buf_rx;
+ if(len < 0) len += p->buf_idx + 1;
+ if(cnt > (uint16)len) cnt = (uint16)len;
+ return cnt;
+}
+
+size_t ina219_getdata(void *pd, uint16 cnt)
+{
+ PINA219DRV p = &ina219drv;
+ if(p->init <= 0) return 0;
+// cnt = ina219_chkdata(cnt);
+ unsigned short *pus = (unsigned short *) pd;
+ taskDISABLE_INTERRUPTS();
+ uint16 buf_rx = p->buf_rx;
+ *pus++ = cnt; // кол-во замеров
+ *pus++ = p->count + p->overrun; // индекс замера для анализа пропусков на стороне приемника
+ // если не пропущено, то равен прошлому + кол-во считанных замеров в прошлом блоке
+ p->count += cnt; // p->overrun = 0;
+ unsigned char *puc = (unsigned char *) pus;
+ if(cnt) {
+ uint16 lend = buf_rx + cnt;
+ if(lend > p->buf_idx) {
+ lend -= p->buf_idx + 1;
+ p->buf_rx = lend;
+ } else {
+ p->buf_rx = lend;
+ lend = 0;
+ };
+ size_t len = (cnt - lend) *sizeof(INA219DATA);
+ if(len) memcpy(puc, (void *)(p->pbuf + buf_rx), len);
+ if(lend) memcpy(puc + len, (void *)p->pbuf, lend *sizeof(INA219DATA));
+ }
+ taskENABLE_INTERRUPTS();
+ return cnt * sizeof(INA219DATA) + 4;
+}
+
+//#define mMIN(a, b) ((ab)?a:b)
+
+#include "web_srv.h"
+#include "websock.h"
+
+int ina219_ws(TCP_SERV_CONN *ts_conn, char cmd)
+{
+ PINA219DRV p = &ina219drv;
+ switch(cmd) {
+ case 'd': // deinit
+ if(p->init > 0) {
+ gtimer_stop(&p->timer);
+ gtimer_deinit(&p->timer);
+ _i2c_deinit(&p->i2c);
+ if(p->pbuf) {
+ free(p->pbuf);
+ p->pbuf = NULL;
+ }
+ p->init = -1;
+ return 0;
+ }
+ return 1;
+ case 'c': // get count
+ return ina219_chkdata(p->buf_idx + 1);
+ case 'i': // init
+ return p->init;
+ default: // get_data
+ if(p->init <= 0) {
+ p->status = 0;
+ p->count = 0;
+ p->overrun = 0;
+ p->errs = 0;
+ if(!p->pbuf) {
+ p->pbuf = zalloc((p->buf_idx + 1) * sizeof(INA219DATA));
+ if(!p->pbuf) {
+ error_printf("Error create buffer!\n");
+ return -1;
+ };
+ p->buf_tx = 0;
+ p->buf_rx = 0;
+ };
+ _i2c_init(&p->i2c);
+ gtimer_init(&p->timer, INA219_TIMER);
+ gtimer_start_periodical(&p->timer, 532*2, (void*)ina_tick_handler, (uint32_t)&ina219drv);
+ p->init = 1;
+// return 0;
+ }
+ case 'g': // get
+ {
+ uint32 i = ina219_chkdata(p->buf_idx + 1);
+ if(i) {
+ WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
+ i = mMIN((web_conn->msgbufsize / sizeof(INA219DATA)), i);
+ if(websock_tx_frame(ts_conn, WS_OPCODE_BINARY | WS_FRAGMENT_FIN, web_conn->msgbuf, ina219_getdata(web_conn->msgbuf, i)) != ERR_OK)
+ return -1;
+ }
+ return i;
+ }
+ }
+ return -1;
+}
+
+void ina219_init(void)
+{
+ PINA219DRV p = &ina219drv;
+ if(p->init <= 0) {
+ rtl_printf("Init INA219\n");
+ p->status = 0;
+ p->count = 0;
+ p->errs = 0;
+ if(!p->pbuf) {
+ p->pbuf = zalloc((p->buf_idx + 1) * sizeof(INA219DATA));
+ if(!p->pbuf) {
+ error_printf("Error create buffer!\n");
+ return;
+ };
+ p->buf_tx = 0;
+ p->buf_rx = 0;
+ };
+// (!) Установки драйвера I2C заданы в структуре ina219drv
+// _i2c_setup(&p->i2c, INA219_I2C_PIN_SDA , INA219_I2C_PIN_SCL, DRV_I2C_FS_MODE); // == DRV_I2C_OK?
+ _i2c_init(&p->i2c);
+// _i2c_set_speed(&p->i2c, INA219_I2C_BUS_CLK);
+ rtl_printf("I2C%d mode = %d, drvStatus = %d\n", p->i2c.idx, p->i2c.mode, p->i2c.status);
+// (!) Рнициализация INA219 перенесена РІ прерывание таймера
+// ina219_write(INA219_REG_CONFIG, p->config);
+// ina219_write(INA219_REG_CALIBRATION, p->calibration);
+ // Initial a periodical timer
+ gtimer_init(&p->timer, INA219_TIMER);
+ // Tick every 0.000532 sec (N*532 Ојs)
+// uint32 tus = (1 << ((p->config >> 3) & 7));
+// tus *= 532;
+ uint32 tus = 532*2;
+ gtimer_start_periodical(&p->timer, tus, (void*)ina_tick_handler, (uint32_t)&ina219drv);
+ rtl_printf("INA219 Timer Period = %u us\n", tus);
+ p->init = 1;
+ }
+}
+
+void ina219_deinit(void)
+{
+ PINA219DRV p = &ina219drv;
+ i2c_drv_t *pi2c = &p->i2c;
+ if(p->init > 0) {
+ rtl_printf("Deinit INA219\n");
+ gtimer_stop(&p->timer);
+ gtimer_deinit(&p->timer);
+// (!) Не используется ina219_write / ina219_read для сокращения кода
+// ina219_write(INA219_REG_CONFIG, INA219_CONFIG_MODE_POWERDOWN);
+ // Break controller.
+ i2c_reg(REG_DW_I2C_IC_ENABLE) |= 2;
+ vTaskDelay(2); // +WDT
+ // Disable controller.
+ i2c_reg(REG_DW_I2C_IC_ENABLE) = 0;
+ vTaskDelay(2); // +WDT
+ // Master Target Address
+ i2c_reg(REG_DW_I2C_IC_TAR) = p->addr;
+ // Enable controller.
+ i2c_reg(REG_DW_I2C_IC_ENABLE) = BIT_IC_ENABLE;
+ // Заполним FIFO ic I2C командой отключения INA219
+ vTaskDelay(2); // +WDT
+ // Write addr reg. INA219 POWER_DOWN
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = INA219_REG_CONFIG;
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = (INA219_CONFIG_MODE_POWERDOWN >> 8);
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = (INA219_CONFIG_MODE_POWERDOWN & 0x0F) | BIT_IC_DATA_CMD_STOP;
+ vTaskDelay(2); // +WDT
+ _i2c_deinit(&p->i2c);
+ if(p->pbuf) {
+ free(p->pbuf);
+ p->pbuf = NULL;
+ }
+ }
+ p->init = 0;
+}
+
+static void ShowIna(void)
+{
+ PINA219DRV p = &ina219drv;
+ rtl_printf("INA219: %d, %d\n", p->buf_i2c.us[0], p->buf_i2c.ss[1]);
+ rtl_printf("INA219: Cnt = %u, Err = %u\n", p->count, p->errs);
+}
+
+static void fATINA(int argc, char *argv[])
+{
+ if(argc > 1) {
+ if(atoi(argv[1])) {
+ ina219_init();
+ vTaskDelay(10); // +WDT
+ }
+ else ina219_deinit();
+ }
+ ShowIna();
+}
+
+MON_RAM_TAB_SECTION COMMAND_TABLE console_commands_ina219[] = {
+ {"ATINA", 0, fATINA, "=[0/1]: INA219 =1 start, =0 stop"}
+};
+
diff --git a/RTLGDB/Project/ina219/ina219drv.h b/RTLGDB/Project/ina219/ina219drv.h
new file mode 100644
index 0000000..7be22af
--- /dev/null
+++ b/RTLGDB/Project/ina219/ina219drv.h
@@ -0,0 +1,55 @@
+/**************************************************************************
+ * Драйвер для INA219
+ **************************************************************************/
+#ifndef _INA219DRV_H_
+#define _INA219DRV_H_
+#include "ina219/ina219.h"
+#include "device.h"
+#include "timer_api.h"
+#include "driver/i2c_drv.h"
+
+typedef struct _ina219_data {
+ union {
+ signed short voltage; // Voltage, 1mV
+ unsigned char vuc[2];
+ } v;
+ union {
+ signed short current; // Current, 50uA?
+ unsigned char iuc[2];
+ } i;
+} INA219DATA, *PINA219DATA;
+
+typedef struct _ina219drv {
+ unsigned char status;
+ unsigned char addr; // адрес INA219 на шине I2C (формат 7 bit)
+ signed char init;
+ unsigned char tmp;
+
+ unsigned short config; // регистр конфигурации INA219
+ unsigned short calibration; // коэф. шунта для INA219
+
+ unsigned short count; // счетчик считанных значений
+ unsigned short overrun; // счет переполнений буфера
+
+ unsigned short errs; // счет ошибок на I2C
+ unsigned short buf_idx; // объем буфера pbuf[buf_idx+1], максимальный индекс-номер замера
+ unsigned short buf_rx; // индекс-номер ещё не считанного замера
+ unsigned short buf_tx; // индекс-номер для записи следующего замера
+ PINA219DATA pbuf;
+ gtimer_t timer;
+ union { // буфер
+ unsigned char uc[4];
+ unsigned short us[2];
+ signed short ss[2];
+ unsigned int ui;
+ } buf_i2c;
+ i2c_drv_t i2c;
+} INA219DRV, *PINA219DRV;
+
+
+#define INA219_I2C_PIN_SDA PC_4
+#define INA219_I2C_PIN_SCL PC_5
+#define INA219_I2C_BUS_CLK 300000 //hz
+#define INA219_TIMER TIMER3 // используемый таймер
+
+#endif // _INA219DRV_H_
diff --git a/RTLGDB/Project/lwipopts.h b/RTLGDB/Project/lwipopts.h
new file mode 100644
index 0000000..7babf72
--- /dev/null
+++ b/RTLGDB/Project/lwipopts.h
@@ -0,0 +1,387 @@
+/**
+ ******************************************************************************
+ * @file lwipopts.h
+ * @author MCD Application Team
+ * @version V1.1.0
+ * @date 07-October-2011
+ * @brief lwIP Options Configuration.
+ * This file is based on Utilities\lwip_v1.3.2\src\include\lwip\opt.h
+ * and contains the lwIP configuration for the STM32F2x7 demonstration.
+ ******************************************************************************
+ * @attention
+ *
+ * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+ * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
+ * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
+ * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
+ * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
+ * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+ *
+ * © COPYRIGHT 2011 STMicroelectronics
+ ******************************************************************************
+ */
+
+#ifndef __LWIPOPTS_H__
+#define __LWIPOPTS_H__
+
+#include
+#include "platform_opts.h"
+
+/**
+ * LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS==1: randomize the local port for the first
+ * local TCP/UDP pcb (default==0). This can prevent creating predictable port
+ * numbers after booting a device.
+ */
+#define LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS 1
+
+#define WIFI_LOGO_CERTIFICATION_CONFIG 1 //for ping 10k test buffer setting
+/**
+ * MEM_LIBC_MALLOC==1: Use malloc/free/realloc provided by your C-library
+ * instead of the lwip internal allocator. Can save code size if you
+ * already use it.
+ */
+#define MEM_LIBC_MALLOC 1
+/**
+* MEMP_MEM_MALLOC==1: Use mem_malloc/mem_free instead of the lwip pool allocator.
+* Especially useful with MEM_LIBC_MALLOC but handle with care regarding execution
+* speed and usage from interrupts!
+*/
+#define MEMP_MEM_MALLOC 1
+
+/**
+ * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain
+ * critical regions during buffer allocation, deallocation and memory
+ * allocation and deallocation.
+ */
+#define SYS_LIGHTWEIGHT_PROT 1
+
+/* Define LWIP_COMPAT_MUTEX if the port has no mutexes and binary semaphores
+ should be used instead */
+#define LWIP_COMPAT_MUTEX 1
+
+#define ETHARP_TRUST_IP_MAC 0
+#define IP_REASSEMBLY 1
+#define IP_FRAG 1
+#define ARP_QUEUEING 0
+
+/**
+ * LWIP_NETIF_HOSTNAME==1: use DHCP_OPTION_HOSTNAME with netif's hostname
+ * field.
+ */
+#define LWIP_NETIF_HOSTNAME 1
+#define LWIP_NETIF_HOSTNAME_SIZE 16
+/**
+ * netif0: DEF_HOSTNAME "0", netif1: DEF_HOSTNAME "1", ..
+ */
+#define DEF_HOSTNAME "rtl871x"
+
+/**
+ * NO_SYS==1: Provides VERY minimal functionality. Otherwise,
+ * use lwIP facilities.
+ */
+#define NO_SYS 0
+
+/* ---------- Memory options ---------- */
+/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which
+ lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2
+ byte alignment -> define MEM_ALIGNMENT to 2. */
+#define MEM_ALIGNMENT 4
+
+/* MEM_SIZE: the size of the heap memory. If the application will send
+a lot of data that needs to be copied, this should be set high. */
+#if WIFI_LOGO_CERTIFICATION_CONFIG
+ #define MEM_SIZE (10*1024) //for ping 10k test
+#else
+ #define MEM_SIZE (5*1024)
+#endif
+
+/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
+ sends a lot of data out of ROM (or other static memory), this
+ should be set high. */
+#define MEMP_NUM_PBUF 100
+/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
+ per active UDP "connection". */
+#define MEMP_NUM_UDP_PCB 6
+/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP
+ connections. */
+#define MEMP_NUM_TCP_PCB 10
+/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP
+ connections. */
+#define MEMP_NUM_TCP_PCB_LISTEN 5
+/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP
+ segments. */
+#define MEMP_NUM_TCP_SEG 20
+/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active
+ timeouts. */
+#define MEMP_NUM_SYS_TIMEOUT 10
+
+
+/* ---------- Pbuf options ---------- */
+/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */
+#if WIFI_LOGO_CERTIFICATION_CONFIG
+ #define PBUF_POOL_SIZE 30 //for ping 10k test
+#else
+ #define PBUF_POOL_SIZE 20
+#endif
+
+/* IP_REASS_MAX_PBUFS: Total maximum amount of pbufs waiting to be reassembled.*/
+#if WIFI_LOGO_CERTIFICATION_CONFIG
+ #define IP_REASS_MAX_PBUFS 30 //for ping 10k test
+#else
+ #define IP_REASS_MAX_PBUFS 10
+#endif
+
+/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */
+#define PBUF_POOL_BUFSIZE 500
+
+
+/* ---------- TCP options ---------- */
+#define LWIP_TCP 1
+#define TCP_TTL 255
+
+/* Controls if TCP should queue segments that arrive out of
+ order. Define to 0 if your device is low on memory. */
+#define TCP_QUEUE_OOSEQ 1
+
+/* TCP Maximum segment size. */
+#define TCP_MSS (1500 - 40) /* TCP_MSS = (Ethernet MTU - IP header size - TCP header size) */
+
+/* TCP sender buffer space (bytes). */
+#define TCP_SND_BUF (5*TCP_MSS)
+
+/* TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least
+ as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. */
+
+#define TCP_SND_QUEUELEN (4* TCP_SND_BUF/TCP_MSS)
+
+/* TCP receive window. */
+#define TCP_WND (4*TCP_MSS) // (2*TCP_MSS)
+
+
+/* ---------- ICMP options ---------- */
+#define LWIP_ICMP 1
+
+/* ---------- ARP options ----------- */
+#define LWIP_ARP 1
+/**
+ * LWIP_AUTOIP==1: Enable AUTOIP module.
+ */
+#define LWIP_AUTOIP 0 //Realtek modified (0->1)
+
+/* ---------- DHCP options ---------- */
+/* Define LWIP_DHCP to 1 if you want DHCP configuration of
+ interfaces. DHCP is not implemented in lwIP 0.5.1, however, so
+ turning this on does currently not work. */
+#define LWIP_DHCP 1
+
+/* ---------- UDP options ---------- */
+#define LWIP_UDP 1
+#define UDP_TTL 255
+/* ---------- DNS options ---------- */
+#define LWIP_DNS 1
+
+/* ---------- UPNP options --------- */
+#define LWIP_UPNP 0
+
+/* Support Multicast */
+#define LWIP_IGMP 1
+
+extern __attribute__ ((long_call)) unsigned int Rand(void);
+#define LWIP_RAND() Rand()
+
+/* Support TCP Keepalive */
+#define LWIP_TCP_KEEPALIVE 1
+
+/*LWIP_UART_ADAPTER==1: Enable LWIP_UART_ADAPTER when CONFIG_GAGENT is enabled,
+ because some GAGENT functions denpond on the following macro definitions.*/
+#if CONFIG_EXAMPLE_UART_ADAPTER
+#define LWIP_UART_ADAPTER 1
+#else
+#define LWIP_UART_ADAPTER 0
+#endif
+
+#if LWIP_UART_ADAPTER
+#undef LWIP_SO_SNDTIMEO
+#define LWIP_SO_SNDTIMEO 1
+
+#undef SO_REUSE
+#define SO_REUSE 1
+
+#undef MEMP_NUM_NETCONN
+#define MEMP_NUM_NETCONN 10
+
+#undef TCP_WND
+#define TCP_WND (4*TCP_MSS)
+
+#define TCP_KEEPIDLE_DEFAULT 10000UL
+#define TCP_KEEPINTVL_DEFAULT 1000UL
+#define TCP_KEEPCNT_DEFAULT 10U
+#endif
+
+#if CONFIG_EXAMPLE_UART_ATCMD
+#undef LWIP_SO_SNDTIMEO
+#define LWIP_SO_SNDTIMEO 1
+
+#undef SO_REUSE
+#define SO_REUSE 1
+
+#undef MEMP_NUM_NETCONN
+#define MEMP_NUM_NETCONN 10
+
+#undef MEMP_NUM_TCP_PCB
+#define MEMP_NUM_TCP_PCB (MEMP_NUM_NETCONN)
+
+#undef MEMP_NUM_UDP_PCB
+#define MEMP_NUM_UDP_PCB (MEMP_NUM_NETCONN)
+
+#undef TCP_WND
+#define TCP_WND (4*TCP_MSS)
+
+#define TCP_KEEPIDLE_DEFAULT 10000UL
+#define TCP_KEEPINTVL_DEFAULT 1000UL
+#define TCP_KEEPCNT_DEFAULT 10U
+
+#define ERRNO 1
+#endif
+
+/* ---------- Statistics options ---------- */
+#define LWIP_STATS 0
+#define LWIP_PROVIDE_ERRNO 1
+
+
+/*
+ --------------------------------------
+ ---------- Checksum options ----------
+ --------------------------------------
+*/
+
+/*
+The STM32F2x7 allows computing and verifying the IP, UDP, TCP and ICMP checksums by hardware:
+ - To use this feature let the following define uncommented.
+ - To disable it and process by CPU comment the the checksum.
+*/
+//Do checksum by lwip - WLAN nic does not support Checksum offload
+//#define CHECKSUM_BY_HARDWARE
+
+
+#ifdef CHECKSUM_BY_HARDWARE
+ /* CHECKSUM_GEN_IP==0: Generate checksums by hardware for outgoing IP packets.*/
+ #define CHECKSUM_GEN_IP 0
+ /* CHECKSUM_GEN_UDP==0: Generate checksums by hardware for outgoing UDP packets.*/
+ #define CHECKSUM_GEN_UDP 0
+ /* CHECKSUM_GEN_TCP==0: Generate checksums by hardware for outgoing TCP packets.*/
+ #define CHECKSUM_GEN_TCP 0
+ /* CHECKSUM_CHECK_IP==0: Check checksums by hardware for incoming IP packets.*/
+ #define CHECKSUM_CHECK_IP 0
+ /* CHECKSUM_CHECK_UDP==0: Check checksums by hardware for incoming UDP packets.*/
+ #define CHECKSUM_CHECK_UDP 0
+ /* CHECKSUM_CHECK_TCP==0: Check checksums by hardware for incoming TCP packets.*/
+ #define CHECKSUM_CHECK_TCP 0
+#else
+ /* CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets.*/
+ #define CHECKSUM_GEN_IP 1
+ /* CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets.*/
+ #define CHECKSUM_GEN_UDP 1
+ /* CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets.*/
+ #define CHECKSUM_GEN_TCP 1
+ /* CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets.*/
+ #define CHECKSUM_CHECK_IP 1
+ /* CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets.*/
+ #define CHECKSUM_CHECK_UDP 1
+ /* CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets.*/
+ #define CHECKSUM_CHECK_TCP 1
+#endif
+
+
+/*
+ ----------------------------------------------
+ ---------- Sequential layer options ----------
+ ----------------------------------------------
+*/
+/**
+ * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c)
+ */
+#define LWIP_NETCONN 1
+
+/*
+ ------------------------------------
+ ---------- Socket options ----------
+ ------------------------------------
+*/
+/**
+ * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c)
+ */
+#define LWIP_SOCKET 1
+
+/*
+ -----------------------------------
+ ---------- DEBUG options ----------
+ -----------------------------------
+*/
+
+#define LWIP_DEBUG 0
+
+/*
+ ---------------------------------
+ ---------- OS options ----------
+ ---------------------------------
+*/
+
+/**
+ * TCPIP_THREAD_STACKSIZE: The stack size used by the main tcpip thread.
+ * The stack size value itself is platform-dependent, but is passed to
+ * sys_thread_new() when the thread is created.
+ */
+#define TCPIP_THREAD_STACKSIZE 1000
+/**
+ * TCPIP_MBOX_SIZE: The mailbox size for the tcpip thread messages
+ * The queue size value itself is platform-dependent, but is passed to
+ * sys_mbox_new() when tcpip_init is called.
+ */
+#define TCPIP_MBOX_SIZE 6
+/**
+ * DEFAULT_UDP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a
+ * NETCONN_UDP. The queue size value itself is platform-dependent, but is passed
+ * to sys_mbox_new() when the recvmbox is created.
+ */
+#define DEFAULT_UDP_RECVMBOX_SIZE 6
+/**
+ * DEFAULT_TCP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a
+ * NETCONN_TCP. The queue size value itself is platform-dependent, but is passed
+ * to sys_mbox_new() when the recvmbox is created.
+ */
+#define DEFAULT_TCP_RECVMBOX_SIZE 6
+/**
+ * DEFAULT_RAW_RECVMBOX_SIZE: The mailbox size for the incoming packets on a
+ * NETCONN_RAW. The queue size value itself is platform-dependent, but is passed
+ * to sys_mbox_new() when the recvmbox is created.
+ */
+#define DEFAULT_RAW_RECVMBOX_SIZE 6
+/**
+ * DEFAULT_ACCEPTMBOX_SIZE: The mailbox size for the incoming connections.
+ * The queue size value itself is platform-dependent, but is passed to
+ * sys_mbox_new() when the acceptmbox is created.
+ */
+#define DEFAULT_ACCEPTMBOX_SIZE 6
+/**
+ * DEFAULT_THREAD_STACKSIZE: The stack size used by any other lwIP thread.
+ * The stack size value itself is platform-dependent, but is passed to
+ * sys_thread_new() when the thread is created.
+ */
+#define DEFAULT_THREAD_STACKSIZE 500
+/**
+ * TCPIP_THREAD_PRIO: The priority assigned to the main tcpip thread.
+ * The priority value itself is platform-dependent, but is passed to
+ * sys_thread_new() when the thread is created.
+ */
+#define TCPIP_THREAD_PRIO (configMAX_PRIORITIES - 2)
+
+/** LWIP_TIMEVAL_PRIVATE: if you want to use the struct timeval provided
+ * by your system, set this to 0 and include in cc.h */
+#if defined(_SYS__TIMEVAL_H_)
+#define LWIP_TIMEVAL_PRIVATE 0
+#endif
+
+#endif /* __LWIPOPTS_H__ */
+
+/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
diff --git a/RTLGDB/Project/main.c b/RTLGDB/Project/main.c
new file mode 100644
index 0000000..3114712
--- /dev/null
+++ b/RTLGDB/Project/main.c
@@ -0,0 +1,97 @@
+#include "platform_autoconf.h"
+#include "autoconf.h"
+#include "FreeRTOS.h"
+#include "task.h"
+#include "diag.h"
+#include "hal_crypto.h"
+#include "hal_log_uart.h"
+#include "hal_misc.h"
+#include "diag.h"
+#include "tcm_heap.h"
+#include "hal_platform.h"
+#include "rtl8195a_sys_on.h"
+#include "hal_timer.h"
+
+#ifdef CONFIG_WDG_ON_IDLE
+#include "rtl8195a_wdt.h"
+#include "hal_peri_on.h"
+#include "rtl8195a_peri_on.h"
+#endif
+
+/* ---------------------------------------------------
+ * Customized Signature (Image Name)
+ * ---------------------------------------------------*/
+#include "section_config.h"
+#ifndef _MSC_VER // IntelliSense
+SECTION(".custom.validate.rodata")
+#endif
+const unsigned char cus_sig[32] = "WEB Sample";
+
+#ifdef CONFIG_DEBUG_LOG
+#define DEBUG_MAIN_LEVEL CONFIG_DEBUG_LOG
+#else
+#define DEBUG_MAIN_LEVEL 0
+#endif
+
+#ifndef CONFIG_INIT_NET
+#define CONFIG_INIT_NET 1
+#endif
+#ifndef CONFIG_INTERACTIVE_MODE
+#define CONFIG_INTERACTIVE_MODE 1
+#endif
+
+extern void WDGStart(void);
+extern void user_init_thrd(void);
+extern void user_init2_thrd(void);
+
+void ShowMemInfo(void)
+{
+ DiagPrintf("\nCLK CPU\t\t%d Hz\nRAM heap\t%d bytes\nTCM heap\t%d bytes\n", HalGetCpuClk(), xPortGetFreeHeapSize(), tcm_heap_freeSpace());
+}
+
+int main(void)
+{
+#if DEBUG_MAIN_LEVEL > 3
+ ConfigDebugErr = -1;
+ ConfigDebugInfo = ~(_DBG_SPI_FLASH_);//|_DBG_TCM_HEAP_);
+ ConfigDebugWarn = -1;
+ CfgSysDebugErr = -1;
+ CfgSysDebugInfo = -1;
+ CfgSysDebugWarn = -1;
+#endif
+
+#ifdef CONFIG_WDG_ON_IDLE
+ HAL_PERI_ON_WRITE32(REG_SOC_FUNC_EN, HAL_PERI_ON_READ32(REG_SOC_FUNC_EN) & 0x1FFFFF);
+#if CONFIG_DEBUG_LOG > 3
+ WDGInitial(CONFIG_WDG_ON_IDLE * 3000); // 30 s
+#else
+ WDGInitial(CONFIG_WDG_ON_IDLE * 1000); // 4 s
+#endif
+ WDGStart();
+#endif
+
+#if (defined(CONFIG_CRYPTO_STARTUP) && (CONFIG_CRYPTO_STARTUP))
+ if(rtl_cryptoEngine_init() != 0 )
+ {
+ DBG_8195A("Crypto engine init failed!\n");
+ }
+#endif
+
+#if DEBUG_MAIN_LEVEL > 1
+ vPortFree(pvPortMalloc(4)); // Init RAM heap
+ ShowMemInfo(); // RAM/TCM/Heaps info
+#endif
+
+ /* wlan & user_start intialization */
+ xTaskCreate(user_init_thrd, "user_init", 1024, NULL, tskIDLE_PRIORITY + 1 + PRIORITIE_OFFSET, NULL);
+ //xTaskCreate(user_init2_thrd, "user_init2", 16384, NULL, tskIDLE_PRIORITY + 1 + PRIORITIE_OFFSET, NULL);
+
+ /*Enable Schedule, Start Kernel*/
+#if defined(CONFIG_KERNEL) && !TASK_SCHEDULER_DISABLED
+#ifdef PLATFORM_FREERTOS
+ vTaskStartScheduler();
+#endif
+#else
+ RtlConsolTaskRom(NULL);
+#endif
+}
diff --git a/RTLGDB/Project/main.h b/RTLGDB/Project/main.h
new file mode 100644
index 0000000..e05a0ab
--- /dev/null
+++ b/RTLGDB/Project/main.h
@@ -0,0 +1,119 @@
+#ifndef MAIN_H
+#define MAIN_H
+
+#include
+
+#ifndef CONFIG_WLAN
+#define CONFIG_WLAN 1
+#endif
+
+/* Header file declaration*/
+void wlan_network();
+
+/* Interactive Mode */
+#define SERIAL_DEBUG_RX 1
+
+/* WLAN and Netork */
+#define STA_MODE_SSID "ap" /* Set SSID here */
+#define AP_MODE_SSID "wlan_ap_ssid" /* Set SSID here */
+#define AP_DEFAULT_CH 6
+#define WLAN0_NAME "wlan0"
+#define WLAN1_NAME "wlan1"
+#define WPA_PASSPHRASE "1234567890" /* Max 32 cahracters */
+#define WEP40_KEY {0x12, 0x34, 0x56, 0x78, 0x90}
+
+#define ATVER_1 1 // For First AT command
+#define ATVER_2 2 // For UART Module AT command
+
+#if CONFIG_EXAMPLE_UART_ATCMD
+#define ATCMD_VER ATVER_2
+#else
+#define ATCMD_VER ATVER_1
+#endif
+
+#if ATCMD_VER == ATVER_2
+
+extern unsigned char sta_ip[4], sta_netmask[4], sta_gw[4];
+extern unsigned char ap_ip[4], ap_netmask[4], ap_gw[4];
+
+/*Static IP ADDRESS*/
+#define IP_ADDR0 sta_ip[0]
+#define IP_ADDR1 sta_ip[1]
+#define IP_ADDR2 sta_ip[2]
+#define IP_ADDR3 sta_ip[3]
+
+/*NETMASK*/
+#define NETMASK_ADDR0 sta_netmask[0]
+#define NETMASK_ADDR1 sta_netmask[1]
+#define NETMASK_ADDR2 sta_netmask[2]
+#define NETMASK_ADDR3 sta_netmask[3]
+
+/*Gateway Address*/
+#define GW_ADDR0 sta_gw[0]
+#define GW_ADDR1 sta_gw[1]
+#define GW_ADDR2 sta_gw[2]
+#define GW_ADDR3 sta_gw[3]
+
+/*******************************************/
+
+/*Static IP ADDRESS*/
+#define AP_IP_ADDR0 ap_ip[0]
+#define AP_IP_ADDR1 ap_ip[1]
+#define AP_IP_ADDR2 ap_ip[2]
+#define AP_IP_ADDR3 ap_ip[3]
+
+/*NETMASK*/
+#define AP_NETMASK_ADDR0 ap_netmask[0]
+#define AP_NETMASK_ADDR1 ap_netmask[1]
+#define AP_NETMASK_ADDR2 ap_netmask[2]
+#define AP_NETMASK_ADDR3 ap_netmask[3]
+
+/*Gateway Address*/
+#define AP_GW_ADDR0 ap_gw[0]
+#define AP_GW_ADDR1 ap_gw[1]
+#define AP_GW_ADDR2 ap_gw[2]
+#define AP_GW_ADDR3 ap_gw[3]
+
+#else
+
+/*Static IP ADDRESS*/
+#define IP_ADDR0 192
+#define IP_ADDR1 168
+#define IP_ADDR2 3
+#define IP_ADDR3 80
+
+/*NETMASK*/
+#define NETMASK_ADDR0 255
+#define NETMASK_ADDR1 255
+#define NETMASK_ADDR2 255
+#define NETMASK_ADDR3 0
+
+/*Gateway Address*/
+#define GW_ADDR0 192
+#define GW_ADDR1 168
+#define GW_ADDR2 3
+#define GW_ADDR3 1
+
+/*******************************************/
+
+/*Static IP ADDRESS*/
+#define AP_IP_ADDR0 192
+#define AP_IP_ADDR1 168
+#define AP_IP_ADDR2 43
+#define AP_IP_ADDR3 1
+
+/*NETMASK*/
+#define AP_NETMASK_ADDR0 255
+#define AP_NETMASK_ADDR1 255
+#define AP_NETMASK_ADDR2 255
+#define AP_NETMASK_ADDR3 0
+
+/*Gateway Address*/
+#define AP_GW_ADDR0 192
+#define AP_GW_ADDR1 168
+#define AP_GW_ADDR2 43
+#define AP_GW_ADDR3 1
+
+#endif //#if ATCMD_VER == ATVER_2
+
+#endif
diff --git a/RTLGDB/Project/platform_autoconf.h b/RTLGDB/Project/platform_autoconf.h
new file mode 100644
index 0000000..26b82b3
--- /dev/null
+++ b/RTLGDB/Project/platform_autoconf.h
@@ -0,0 +1,255 @@
+/*
+ * Automatically generated by make menuconfig: don't edit
+ */
+#define AUTOCONF_INCLUDED
+
+#define RTL8710AF
+#define RTL8711AM
+
+/* Image1 on project */
+#define PRESENT_IMAGE1
+/* Image2 on project */
+#define PRESENT_IMAGE2
+/*
+ * Target Platform Selection
+ */
+#define CONFIG_USE_TCM_HEAP 1
+#define configUSE_STACK_TCM_HEAP 5 // min priority use tcm ?
+
+#define CONFIG_WITHOUT_MONITOR 1
+
+#undef CONFIG_RTL8195A
+#define CONFIG_RTL8195A 1
+#undef CONFIG_FPGA
+#undef CONFIG_RTL_SIM
+#undef CONFIG_POST_SIM
+/*
+ * < Mass Production Option
+ */
+#undef CONFIG_MP
+#undef CONFIG_CP
+#undef CONFIG_FT
+#define RTL8195A 1
+/* 0 - 166666666 Hz, 1 - 83333333 Hz, 2 - 41666666 Hz, 3 - 20833333 Hz, 4 - 10416666 Hz, 5 - 4000000? Hz,
+ 6 - 200000000 Hz, 7 - 10000000 Hz, 8 - 50000000 Hz, 9 - 25000000 Hz, 10 - 12500000 Hz, 11 - 4000000? Hz */
+#define CONFIG_CPU_CLK 1
+//166.6MHZ - RUN/IDLE/SLP ~63/21/6.4 mA
+//83.3MHZ - RUN/IDLE/SLP ~55/15/6.4 mA
+//41.6MHZ - RUN/IDLE ~51/11 mA
+//20.8MHZ - RUN/IDLE ~49/9.5 mA
+//4MHZ - IDLE ~8 mA
+#undef CONFIG_FPGA_CLK
+#define CONFIG_SDR_CLK 1
+#define CONFIG_SDR_100MHZ 1
+#undef CONFIG_SDR_50MHZ
+#undef CONFIG_SDR_25MHZ
+#undef CONFIG_SDR_12_5MHZ
+#define SDR_CLOCK_SEL_VALUE (0)
+#define CONFIG_BOOT_PROCEDURE 1
+#define CONFIG_IMAGE_PAGE_LOAD 1
+#undef CONFIG_IMAGE_AUTO_LOAD
+#undef CONFIG_IMAGE_PAGE_LOAD
+//#define CONFIG_IMAGE_AUTO_LOAD 1
+//#define CONFIG_BOOT_TO_UPGRADE_IMG2 1
+#undef CONFIG_PERI_UPDATE_IMG
+#define CONFIG_BOOT_FROM_JTAG 1
+#undef CONFIG_ALIGNMENT_EXCEPTION_ENABLE
+#define CONFIG_KERNEL 1
+#define PLATFORM_FREERTOS 1
+#undef PLATFORM_UCOSII
+#undef PLATFORM_ECOS
+#undef CONFIG_TASK_SCHEDUL_DIS
+#define TASK_SCHEDULER_DISABLED (0)
+#define CONFIG_NORMALL_MODE 1
+#undef CONFIG_MEMORY_VERIFY_MODE
+#define CONFIG_TIMER_EN 1
+#define CONFIG_TIMER_NORMAL 1
+#undef CONFIG_TIMER_TEST
+#define CONFIG_TIMER_MODULE 1
+#define CONFIG_WDG 1
+#undef CONFIG_WDG_NON
+#define CONFIG_WDG_NORMAL 1
+#define CONFIG_WDG_ON_IDLE 4 // 10 // add pvvx: wdt on 10 s -> main.c + tasks.c
+#define CONFIG_GDMA_EN 1
+#define CONFIG_GDMA_NORMAL 1
+#undef CONFIG_GDMA_TEST
+#define CONFIG_GDMA_MODULE 1
+#define CONFIG_WIFI_EN 1
+#define CONFIG_WIFI_NORMAL 1
+#undef CONFIG_WIFI_TEST
+#define CONFIG_WIFI_MODULE 1
+#define CONFIG_GPIO_EN 1
+#define CONFIG_GPIO_NORMAL 1
+#undef CONFIG_GPIO_TEST
+#define CONFIG_GPIO_MODULE 1
+#if defined(CONFIG_INIC) || (CONFIG_SDIOD)
+#define CONFIG_SDIO_DEVICE_EN 1
+#define CONFIG_SDIO_DEVICE_NORMAL 1
+#undef CONFIG_SDIO_DEVICE_TEST
+#define CONFIG_SDIO_DEVICE_MODULE 1
+#else
+#undef CONFIG_SDIO_DEVICE_EN
+#endif
+#define CONFIG_SDIO_HOST_EN 1
+//#define CONFIG_USB_EN 1
+#undef CONFIG_USB_NORMAL
+#define CONFIG_USB_TEST 1
+#define CONFIG_USB_MODULE 1
+#define CONFIG_USB_VERIFY 1
+#undef CONFIG_USB_ROM_LIB
+//#define CONFIG_USB_DBGINFO_EN 1
+#if defined(CONFIG_INIC) || (CONFIG_USBD)
+#define DWC_DEVICE_ONLY 1
+#else
+#define DWC_HOST_ONLY 1
+#define CONFIG_USB_HOST_ONLY 1
+#endif
+#define CONFIG_SPI_COM_EN 1
+#define CONFIG_SPI_COM_NORMAL 1
+#undef CONFIG_SPI_COM_TEST
+#define CONFIG_SPI_COM_MODULE 1
+#define CONFIG_UART_EN 1
+#define CONFIG_UART_NORMAL 1
+#undef CONFIG_UART_TEST
+#define CONFIG_UART_MODULE 1
+#define CONFIG_I2C_EN 1
+#define CONFIG_I2C_NORMAL 1
+#undef CONFIG_I2C_TEST
+#define CONFIG_I2C_MODULE 1
+#undef CONFIG_DEBUG_LOG_I2C_HAL
+#undef CONFIG_PCM_EN
+#define CONFIG_I2S_EN 1
+#define CONFIG_I2S_NORMAL 1
+#undef CONFIG_I2S_TEST
+#define CONFIG_I2S_MODULE 1
+#undef CONFIG_DEBUG_LOG_I2S_HAL
+#define CONFIG_NFC_EN 1
+#define CONFIG_NFC_NORMAL 1
+#undef CONFIG_NFC_TEST
+#define CONFIG_NFC_MODULE 1
+#define CONFIG_SOC_PS_EN 1
+#define CONFIG_SOC_PS_NORMAL 1
+#undef CONFIG_SOC_PS_TEST
+#define CONFIG_SOC_PS_MODULE 1 // hal_soc_ps_monitor.c
+//#define CONFIG_SOC_PS_VERIFY 1 // hal_soc_ps_monitor.c
+#define CONFIG_CRYPTO_EN 1
+#define CONFIG_CRYPTO_NORMAL 1
+#undef CONFIG_CRYPTO_TEST
+#define CONFIG_CRYPTO_MODULE 1
+#define CONFIG_CRYPTO_STARTUP 1
+#define CONFIG_MII_EN 0 //1
+#define CONFIG_PWM_EN 1
+#define CONFIG_PWM_NORMAL 1
+#undef CONFIG_PWM_TEST
+#define CONFIG_PWM_MODULE 1
+#define CONFIG_EFUSE_EN 1 // common/mbed/targets/hal/rtl8195a/efuse_api.c
+#define CONFIG_EFUSE_NORMAL 1
+#undef CONFIG_EFUSE_TEST
+#define CONFIG_EFUSE_MODULE 1
+#if defined(RTL8711AM) || defined(USE_SDRAM)
+#define CONFIG_SDR_EN 1
+#endif
+#define CONFIG_SDR_NORMAL 1
+#undef CONFIG_SDR_TEST
+#define CONFIG_SDR_MODULE 1
+#define CONFIG_SPIC_EN 1
+#define CONFIG_SPIC_NORMAL 1
+#undef CONFIG_SPIC_TEST
+#define CONFIG_SPIC_MODULE 1
+#define CONFIG_ADC_EN 1
+#define CONFIG_DAC_EN 1
+#define CONFIG_NOR_FLASH 1
+#undef CONFIG_SPI_FLASH
+#undef CONFIG_NAND_FLASH
+#undef CONFIG_NONE_FLASH
+#undef CONFIG_BTBX_EN
+
+// add pvvx
+#define CONFIG_LOG_UART_EN 1
+
+/*
+ * < Engineer Mode Config
+ */
+#undef CONFIG_JTAG
+#undef CONFIG_COMPILE_FLASH_DOWNLOAD_CODE
+#undef CONIFG_COMPILE_EXTERNAL_SRAM_CALIBRATE
+#undef CONFIG_CMSIS_MATH_LIB_EN
+
+/*
+ * < Application Config
+ */
+#define CONFIG_NETWORK 1
+#define CONFIG_RTLIB_EN 1
+#define CONFIG_RTLIB_NORMAL 1
+#undef CONFIG_RTLIB_TEST
+#define CONFIG_RTLIB_MODULE 1
+
+/*
+ * < System Debug Message Config
+ */
+#define CONFIG_UART_LOG_HISTORY 1
+#undef CONFIG_CONSOLE_NORMALL_MODE
+#define CONFIG_CONSOLE_VERIFY_MODE 1
+
+/* CONFIG_DEBUG_LOG:
+=0 Off all diag/debug msg,
+=1 Only errors,
+=2 errors + warning, (default)
+=3 errors + warning + info,
+=4 errors + warning + info + debug,
+=5 full */
+#define CONFIG_DEBUG_LOG 2
+#if CONFIG_DEBUG_LOG > 0
+//#define CONFIG_DEBUG_ERR_MSG 1
+#define CONFIG_DEBUG_LOG_ADC_HAL 1
+#define CONFIG_DEBUG_LOG_I2S_HAL 1
+//#undef CONFIG_DEBUG_WARN_MSG
+//#undef CONFIG_DEBUG_INFO_MSG
+#endif // CONFIG_DEBUG_LOG
+/*
+ * < SDK Option Config
+ */
+#undef CONFIG_MBED_ENABLED
+#undef CONFIG_APP_DEMO
+
+/*
+ * < Select Chip Version
+ */
+#undef CONFIG_CHIP_A_CUT
+#define CONFIG_CHIP_B_CUT 1
+#undef CONFIG_CHIP_C_CUT
+#undef CONFIG_CHIP_E_CUT
+
+/*
+ * < Select toolchain
+ */
+#undef CONFIG_TOOLCHAIN_ASDK
+#undef CONFIG_TOOLCHAIN_ARM_GCC
+
+/*
+ * < Build Option
+ */
+#define CONFIG_LINK_ROM_LIB 1
+#undef CONFIG_LINK_ROM_SYMB
+#undef CONFIG_NORMAL_BUILD
+#undef CONFIG_RELEASE_BUILD
+#undef CONFIG_RELEASE_BUILD_LIBRARIES
+#undef CONFIG_LIB_BUILD_RAM
+#define CONFIG_RELEASE_BUILD_RAM_ALL 1
+#undef CONFIG_IMAGE_ALL
+#define CONFIG_IMAGE_SEPARATE 1
+
+#if CONFIG_CPU_CLK < 6
+#define CPU_CLOCK_SEL_DIV5_3 0
+#define CPU_CLOCK_SEL_VALUE CONFIG_CPU_CLK
+#else
+#define CPU_CLOCK_SEL_DIV5_3 1
+#define CPU_CLOCK_SEL_VALUE (CONFIG_CPU_CLK-6)
+#endif
+
+#if CPU_CLOCK_SEL_DIV5_3
+#define PLATFORM_CLOCK (200000000ul>>CPU_CLOCK_SEL_VALUE)
+#else
+#define PLATFORM_CLOCK (((200000000ul*5ul)/6ul)>>CPU_CLOCK_SEL_VALUE)
+#endif
+
diff --git a/RTLGDB/Project/platform_opts.h b/RTLGDB/Project/platform_opts.h
new file mode 100644
index 0000000..6ab6663
--- /dev/null
+++ b/RTLGDB/Project/platform_opts.h
@@ -0,0 +1,172 @@
+/**
+ ******************************************************************************
+ *This file contains general configurations for ameba platform
+ ******************************************************************************
+*/
+
+#ifndef __PLATFORM_OPTS_H__
+#define __PLATFORM_OPTS_H__
+
+/*For MP mode setting*/
+#define SUPPORT_MP_MODE 0
+
+/**
+ * For AT cmd Log service configurations
+ */
+#define SUPPORT_LOG_SERVICE 0
+#if SUPPORT_LOG_SERVICE
+#define LOG_SERVICE_BUFLEN 100 //can't larger than UART_LOG_CMD_BUFLEN(127)
+#define CONFIG_LOG_HISTORY 0
+#if CONFIG_LOG_HISTORY
+#define LOG_HISTORY_LEN 5
+#endif
+#define SUPPORT_INTERACTIVE_MODE 0 //on/off wifi_interactive_mode
+#define CONFIG_LOG_SERVICE_LOCK 0
+#endif
+
+/**
+ * For interactive mode configurations, depends on log service
+ */
+#if SUPPORT_INTERACTIVE_MODE
+#define CONFIG_INTERACTIVE_MODE 1
+#define CONFIG_INTERACTIVE_EXT 0
+#else
+#define CONFIG_INTERACTIVE_MODE 0
+#define CONFIG_INTERACTIVE_EXT 0
+#endif
+
+/**
+ * For FreeRTOS tickless configurations
+ */
+#define FREERTOS_PMU_TICKLESS_PLL_RESERVED 0 // In sleep mode, 0: close PLL clock, 1: reserve PLL clock
+#define FREERTOS_PMU_TICKLESS_SUSPEND_SDRAM 0 // In sleep mode, 1: suspend SDRAM, 0: no act
+
+/******************************************************************************/
+
+/**
+* For common flash usage
+*/
+#define AP_SETTING_SECTOR 0x000FE000
+#define UART_SETTING_SECTOR 0x000FC000
+#define FAST_RECONNECT_DATA (0x80000 - 0x1000)
+
+/**
+ * For Wlan configurations
+ */
+
+#define CONFIG_WLAN 1
+#if CONFIG_WLAN
+#define CONFIG_LWIP_LAYER 1
+#define CONFIG_AT_USR 1 // add pvxx
+//#define CONFIG_AT_LWIP 1 // add pvxx
+//#define CONFIG_AT_SYS 1 // add pvxx
+//#define CONFIG_AT_WIFI 1 // add pvxx
+#define CONFIG_INIT_NET 1 // init lwip layer when start up
+#define CONFIG_WIFI_IND_USE_THREAD 0 // wifi indicate worker thread
+
+//on/off relative commands in log service
+#define CONFIG_SSL_CLIENT 0
+#define CONFIG_WEBSERVER 0
+#define CONFIG_OTA_UPDATE 1
+#define CONFIG_BSD_TCP 1 //NOTE : Enable CONFIG_BSD_TCP will increase about 11KB code size
+#define CONFIG_AIRKISS 0 //on or off tencent airkiss
+#define CONFIG_UART_SOCKET 0 // Set: CONFIG_UART_EN, CONFIG_UART_SOCKET
+#define CONFIG_UART_XMODEM 0 //support uart xmodem upgrade or not
+#define CONFIG_TRANSPORT 0 //on or off the at command for transport socket
+
+/* For WPS and P2P */
+#define CONFIG_ENABLE_WPS 0
+#define CONFIG_ENABLE_P2P 0
+#if CONFIG_ENABLE_P2P
+#define CONFIG_ENABLE_WPS_AP 1
+#undef CONFIG_WIFI_IND_USE_THREAD
+#define CONFIG_WIFI_IND_USE_THREAD 1
+#endif
+#if (CONFIG_ENABLE_P2P && ((CONFIG_ENABLE_WPS_AP == 0) || (CONFIG_ENABLE_WPS == 0)))
+#error "If CONFIG_ENABLE_P2P, need to define CONFIG_ENABLE_WPS_AP 1"
+#endif
+
+/* For Simple Link */
+#define CONFIG_INCLUDE_SIMPLE_CONFIG 0
+
+/*For wowlan service settings*/
+#define CONFIG_WOWLAN_SERVICE 0
+
+#endif //end of #if CONFIG_WLAN
+/*******************************************************************************/
+
+/**
+ * For Ethernet configurations
+ */
+#define CONFIG_ETHERNET 0
+#if CONFIG_ETHERNET
+
+#define CONFIG_LWIP_LAYER 1
+#define CONFIG_INIT_NET 1 //init lwip layer when start up
+
+//on/off relative commands in log service
+#define CONFIG_SSL_CLIENT 0
+#define CONFIG_BSD_TCP 0 //NOTE : Enable CONFIG_BSD_TCP will increase about 11KB code size
+
+#endif
+
+
+/**
+ * For iNIC configurations
+ */
+#ifdef CONFIG_INIC //this flag is defined in IAR project
+#define CONFIG_INIC_EN 1 //enable iNIC mode
+#undef CONFIG_ENABLE_WPS
+#define CONFIG_ENABLE_WPS 1
+#undef CONFIG_INCLUDE_SIMPLE_CONFIG
+#define CONFIG_INCLUDE_SIMPLE_CONFIG 1
+#undef CONFIG_WOWLAN_SERVICE
+#define CONFIG_WOWLAN_SERVICE 1
+#undef LOG_SERVICE_BUFLEN
+#define LOG_SERVICE_BUFLEN 256
+#undef CONFIG_LWIP_LAYER
+#define CONFIG_LWIP_LAYER 0
+#undef CONFIG_OTA_UPDATE
+#define CONFIG_OTA_UPDATE 0
+#undef CONFIG_EXAMPLE_WLAN_FAST_CONNECT
+#define CONFIG_EXAMPLE_WLAN_FAST_CONNECT 0
+#define CONFIG_INIC_SDIO_HCI 1 //for SDIO or USB iNIC
+#define CONFIG_INIC_USB_HCI 0
+#define CONFIG_INIC_CMD_RSP 1 //need to return msg to host
+#endif
+/******************End of iNIC configurations*******************/
+
+/* For UART Module AT command example */
+#define CONFIG_EXAMPLE_UART_ATCMD 0
+#if CONFIG_EXAMPLE_UART_ATCMD
+#undef FREERTOS_PMU_TICKLESS_PLL_RESERVED
+#define FREERTOS_PMU_TICKLESS_PLL_RESERVED 1
+#undef CONFIG_OTA_UPDATE
+#define CONFIG_OTA_UPDATE 1
+#undef CONFIG_TRANSPORT
+#define CONFIG_TRANSPORT 1
+#undef LOG_SERVICE_BUFLEN
+#define LOG_SERVICE_BUFLEN 1600
+#undef CONFIG_LOG_SERVICE_LOCK
+#define CONFIG_LOG_SERVICE_LOCK 1
+#else
+#define CONFIG_EXAMPLE_WLAN_FAST_CONNECT 0
+#endif
+
+//#define CONFIG_EXAMPLE_UART_ADAPTER 1
+//#define CONFIG_EXAMPLE_MDNS
+#define USE_FLASH_EEP 1
+#define CONFIG_WLAN_CONNECT_CB 0
+
+//#define CONFIG_FATFS_EN 1 // FatFs & SD
+#ifdef CONFIG_FATFS_EN
+// fatfs version
+#define FATFS_R_10C
+// fatfs disk interface
+#define FATFS_DISK_USB 0
+#define FATFS_DISK_SD 1
+#undef CONFIG_SDIO_HOST_EN
+#define CONFIG_SDIO_HOST_EN 1
+#endif
+
+#endif //__PLATFORM_OPTS_H__
diff --git a/RTLGDB/Project/rtl8195a/c_types.h b/RTLGDB/Project/rtl8195a/c_types.h
new file mode 100644
index 0000000..4a65a4d
--- /dev/null
+++ b/RTLGDB/Project/rtl8195a/c_types.h
@@ -0,0 +1,92 @@
+#ifndef _C_TYPES_H_
+#define _C_TYPES_H_
+/*
+typedef unsigned char uint8_t;
+typedef signed char sint8_t;
+typedef signed char int8_t;
+typedef unsigned short uint16_t;
+typedef signed short sint16_t;
+typedef signed short int16_t;
+typedef unsigned long uint32_t;
+typedef signed long sint32_t;
+typedef signed long int32_t;
+typedef signed long long sint64_t;
+typedef unsigned long long uint64_t;
+typedef unsigned long long u_int64_t;
+typedef float real32_t;
+typedef double real64_t;
+
+typedef unsigned char uint8;
+typedef unsigned char uint8_t;
+typedef signed char sint8;
+typedef signed char int8;
+typedef signed char int8_t;
+typedef unsigned short uint16;
+typedef unsigned short uint16_t;
+typedef signed short sint16;
+typedef signed short int16_t;
+typedef unsigned int uint32;
+typedef unsigned int u_int;
+typedef unsigned int uint32_t;
+typedef signed int sint32;
+typedef signed int int32_t;
+typedef int int32;
+typedef signed long long sint64;
+typedef unsigned long long uint64;
+typedef unsigned long long uint64_t;
+typedef float real32;
+typedef double real64;
+*/
+
+#define __le16 uint16_t
+
+typedef unsigned int size_t;
+typedef int ssize_t;
+
+#ifndef _SYS_CDEFS_H_
+#define __packed __attribute__((packed))
+#endif
+
+#define static static
+
+#ifndef NULL
+#define NULL (void *)0
+#endif /* NULL */
+
+/* probably should not put STATUS here */
+typedef enum {
+ OK = 0,
+ FAIL,
+ PENDING,
+ BUSY,
+ CANCEL,
+} STATUS;
+
+#define BIT(nr) (1UL << (nr))
+
+#define REG_SET_BIT(_r, _b) (*(volatile uint32_t*)(_r) |= (_b))
+#define REG_CLR_BIT(_r, _b) (*(volatile uint32_t*)(_r) &= ~(_b))
+
+#define DMEM_ATTR
+#define SHMEM_ATTR
+
+#ifdef ICACHE_FLASH
+#define ICACHE_FLASH_ATTR
+#define ICACHE_RODATA_ATTR
+#else
+#define ICACHE_FLASH_ATTR
+#define ICACHE_RODATA_ATTR
+#endif /* ICACHE_FLASH */
+
+#ifndef __cplusplus
+typedef unsigned char bool;
+//#define BOOL bool
+#define true (1)
+#define false (0)
+#define TRUE true
+#define FALSE false
+
+
+#endif /* !__cplusplus */
+
+#endif /* _C_TYPES_H_ */
diff --git a/RTLGDB/Project/rtl8195a/os.h b/RTLGDB/Project/rtl8195a/os.h
new file mode 100644
index 0000000..b6353ba
--- /dev/null
+++ b/RTLGDB/Project/rtl8195a/os.h
@@ -0,0 +1,593 @@
+/*
+ * OS specific functions
+ * Copyright (c) 2005-2009, Jouni Malinen
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef OS_H
+#define OS_H
+
+//#include "basic_types.h"
+#include
+#include "osdep_service.h"
+#include "freertos/wrapper.h"
+#include "utils/rom/rom_wps_os.h"
+
+typedef void* xqueue_handle_t;
+
+typedef long os_time_t;
+
+typedef _timer os_timer;
+
+/**
+ * os_sleep - Sleep (sec, usec)
+ * @sec: Number of seconds to sleep
+ * @usec: Number of microseconds to sleep
+ */
+void os_sleep(os_time_t sec, os_time_t usec);
+
+struct os_time {
+ os_time_t sec;
+ os_time_t usec;
+};
+
+struct os_reltime {
+ os_time_t sec;
+ os_time_t usec;
+};
+
+/**
+ * os_get_time - Get current time (sec, usec)
+ * @t: Pointer to buffer for the time
+ * Returns: 0 on success, -1 on failure
+ */
+int os_get_time(struct os_time *t);
+
+int os_get_reltime(struct os_reltime *t);
+/* Helper macros for handling struct os_time */
+/* (&timeout->time, &tmp->time) */
+#define os_time_before(a, b) \
+ ((a)->sec < (b)->sec || \
+ ((a)->sec == (b)->sec && (a)->usec < (b)->usec))
+
+#define os_time_sub(a, b, res) do { \
+ (res)->sec = (a)->sec - (b)->sec; \
+ (res)->usec = (a)->usec - (b)->usec; \
+ if ((res)->usec < 0) { \
+ (res)->sec--; \
+ (res)->usec += 1000000; \
+ } \
+} while (0)
+
+/**
+ * os_mktime - Convert broken-down time into seconds since 1970-01-01
+ * @year: Four digit year
+ * @month: Month (1 .. 12)
+ * @day: Day of month (1 .. 31)
+ * @hour: Hour (0 .. 23)
+ * @min: Minute (0 .. 59)
+ * @sec: Second (0 .. 60)
+ * @t: Buffer for returning calendar time representation (seconds since
+ * 1970-01-01 00:00:00)
+ * Returns: 0 on success, -1 on failure
+ *
+ * Note: The result is in seconds from Epoch, i.e., in UTC, not in local time
+ * which is used by POSIX mktime().
+ */
+int os_mktime(int year, int month, int day, int hour, int min, int sec,
+ os_time_t *t);
+
+struct os_tm {
+ int sec; /* 0..59 or 60 for leap seconds */
+ int min; /* 0..59 */
+ int hour; /* 0..23 */
+ int day; /* 1..31 */
+ int month; /* 1..12 */
+ int year; /* Four digit year */
+};
+
+int os_gmtime(os_time_t t, struct os_tm *tm);
+
+/* Helpers for handling struct os_time */
+
+/* Helpers for handling struct os_reltime */
+
+static inline int os_reltime_before(struct os_reltime *a,
+ struct os_reltime *b)
+{
+ return os_time_before(a,b);
+}
+
+
+static inline void os_reltime_sub(struct os_reltime *a, struct os_reltime *b,
+ struct os_reltime *res)
+{
+ os_time_sub(a,b,res);
+}
+
+
+static inline void os_reltime_age(struct os_reltime *start,
+ struct os_reltime *age)
+{
+ struct os_reltime now;
+
+ os_get_time((struct os_time *)&now);
+ os_reltime_sub(&now, start, age);
+}
+
+
+static inline int os_reltime_expired(struct os_reltime *now,
+ struct os_reltime *ts,
+ os_time_t timeout_secs)
+{
+ struct os_reltime age;
+
+ os_reltime_sub(now, ts, &age);
+ return (age.sec > timeout_secs) ||
+ (age.sec == timeout_secs && age.usec > 0);
+}
+
+/**
+ * os_daemonize - Run in the background (detach from the controlling terminal)
+ * @pid_file: File name to write the process ID to or %NULL to skip this
+ * Returns: 0 on success, -1 on failure
+ */
+int os_daemonize(const char *pid_file);
+
+/**
+ * os_daemonize_terminate - Stop running in the background (remove pid file)
+ * @pid_file: File name to write the process ID to or %NULL to skip this
+ */
+void os_daemonize_terminate(const char *pid_file);
+
+/**
+ * os_get_random - Get cryptographically strong pseudo random data
+ * @buf: Buffer for pseudo random data
+ * @len: Length of the buffer
+ * Returns: 0 on success, -1 on failure
+ */
+int os_get_random(unsigned char *buf, size_t len);
+
+/**
+ * os_random - Get pseudo random value (not necessarily very strong)
+ * Returns: Pseudo random value
+ */
+unsigned long os_random(void);
+
+/**
+ * os_rel2abs_path - Get an absolute path for a file
+ * @rel_path: Relative path to a file
+ * Returns: Absolute path for the file or %NULL on failure
+ *
+ * This function tries to convert a relative path of a file to an absolute path
+ * in order for the file to be found even if current working directory has
+ * changed. The returned value is allocated and caller is responsible for
+ * freeing it. It is acceptable to just return the same path in an allocated
+ * buffer, e.g., return strdup(rel_path). This function is only used to find
+ * configuration files when os_daemonize() may have changed the current working
+ * directory and relative path would be pointing to a different location.
+ */
+char * os_rel2abs_path(const char *rel_path);
+
+/**
+ * os_program_init - Program initialization (called at start)
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function is called when a programs starts. If there are any OS specific
+ * processing that is needed, it can be placed here. It is also acceptable to
+ * just return 0 if not special processing is needed.
+ */
+int os_program_init(void);
+
+/**
+ * os_program_deinit - Program deinitialization (called just before exit)
+ *
+ * This function is called just before a program exists. If there are any OS
+ * specific processing, e.g., freeing resourced allocated in os_program_init(),
+ * it should be done here. It is also acceptable for this function to do
+ * nothing.
+ */
+void os_program_deinit(void);
+
+/**
+ * os_setenv - Set environment variable
+ * @name: Name of the variable
+ * @value: Value to set to the variable
+ * @overwrite: Whether existing variable should be overwritten
+ * Returns: 0 on success, -1 on error
+ *
+ * This function is only used for wpa_cli action scripts. OS wrapper does not
+ * need to implement this if such functionality is not needed.
+ */
+int os_setenv(const char *name, const char *value, int overwrite);
+
+/**
+ * os_unsetenv - Delete environent variable
+ * @name: Name of the variable
+ * Returns: 0 on success, -1 on error
+ *
+ * This function is only used for wpa_cli action scripts. OS wrapper does not
+ * need to implement this if such functionality is not needed.
+ */
+int os_unsetenv(const char *name);
+
+/**
+ * os_readfile - Read a file to an allocated memory buffer
+ * @name: Name of the file to read
+ * @len: For returning the length of the allocated buffer
+ * Returns: Pointer to the allocated buffer or %NULL on failure
+ *
+ * This function allocates memory and reads the given file to this buffer. Both
+ * binary and text files can be read with this function. The caller is
+ * responsible for freeing the returned buffer with os_free().
+ */
+char * os_readfile(const char *name, size_t *len);
+
+//#if 0
+/**
+ * os_zalloc - Allocate and zero memory
+ * @size: Number of bytes to allocate
+ * Returns: Pointer to allocated and zeroed memory or %NULL on failure
+ *
+ * Caller is responsible for freeing the returned buffer with os_free().
+ */
+void * os_zalloc(size_t size);
+
+/**
+ * os_calloc - Allocate and zero memory for an array
+ * @nmemb: Number of members in the array
+ * @size: Number of bytes in each member
+ * Returns: Pointer to allocated and zeroed memory or %NULL on failure
+ *
+ * This function can be used as a wrapper for os_zalloc(nmemb * size) when an
+ * allocation is used for an array. The main benefit over os_zalloc() is in
+ * having an extra check to catch integer overflows in multiplication.
+ *
+ * Caller is responsible for freeing the returned buffer with os_free().
+ */
+static inline void * os_calloc(size_t nmemb, size_t size)
+{
+ if (size && nmemb > (~(size_t) 0) / size)
+ return NULL;
+ return os_zalloc(nmemb * size);
+}
+//#endif
+
+
+static inline int os_memcmp_const(const void *a, const void *b, size_t len)
+{
+ const uint8_t *aa = a;
+ const uint8_t *bb = b;
+ size_t i;
+ uint8_t res;
+
+ for (res = 0, i = 0; i < len; i++)
+ res |= aa[i] ^ bb[i];
+
+ return res;
+}
+
+/*
+ * The following functions are wrapper for standard ANSI C or POSIX functions.
+ * By default, they are just defined to use the standard function name and no
+ * os_*.c implementation is needed for them. This avoids extra function calls
+ * by allowing the C pre-processor take care of the function name mapping.
+ *
+ * If the target system uses a C library that does not provide these functions,
+ * build_config.h can be used to define the wrappers to use a different
+ * function name. This can be done on function-by-function basis since the
+ * defines here are only used if build_config.h does not define the os_* name.
+ * If needed, os_*.c file can be used to implement the functions that are not
+ * included in the C library on the target system. Alternatively,
+ * OS_NO_C_LIB_DEFINES can be defined to skip all defines here in which case
+ * these functions need to be implemented in os_*.c file for the target system.
+ */
+
+#ifdef OS_NO_C_LIB_DEFINES
+
+/**
+ * os_malloc - Allocate dynamic memory
+ * @size: Size of the buffer to allocate
+ * Returns: Allocated buffer or %NULL on failure
+ *
+ * Caller is responsible for freeing the returned buffer with os_free().
+ */
+void * os_malloc(size_t size);
+
+/**
+ * os_realloc - Re-allocate dynamic memory
+ * @ptr: Old buffer from os_malloc() or os_realloc()
+ * @size: Size of the new buffer
+ * Returns: Allocated buffer or %NULL on failure
+ *
+ * Caller is responsible for freeing the returned buffer with os_free().
+ * If re-allocation fails, %NULL is returned and the original buffer (ptr) is
+ * not freed and caller is still responsible for freeing it.
+ */
+void * os_realloc(void *ptr, size_t size);
+
+/**
+ * os_free - Free dynamic memory
+ * @ptr: Old buffer from os_malloc() or os_realloc(); can be %NULL
+ */
+void os_free(void *ptr);
+
+/**
+ * os_memcpy - Copy memory area
+ * @dest: Destination
+ * @src: Source
+ * @n: Number of bytes to copy
+ * Returns: dest
+ *
+ * The memory areas src and dst must not overlap. os_memmove() can be used with
+ * overlapping memory.
+ */
+void * os_memcpy(void *dest, const void *src, size_t n);
+
+/**
+ * os_memmove - Copy memory area
+ * @dest: Destination
+ * @src: Source
+ * @n: Number of bytes to copy
+ * Returns: dest
+ *
+ * The memory areas src and dst may overlap.
+ */
+void *os_memmove(void *dest, const void *src, size_t n);
+
+/**
+ * os_memset - Fill memory with a constant byte
+ * @s: Memory area to be filled
+ * @c: Constant byte
+ * @n: Number of bytes started from s to fill with c
+ * Returns: s
+ */
+void *os_memset(void *s, int c, size_t n);
+
+/**
+ * os_memcmp - Compare memory areas
+ * @s1: First buffer
+ * @s2: Second buffer
+ * @n: Maximum numbers of octets to compare
+ * Returns: An integer less than, equal to, or greater than zero if s1 is
+ * found to be less than, to match, or be greater than s2. Only first n
+ * characters will be compared.
+ */
+int os_memcmp(const void *s1, const void *s2, size_t n);
+
+/**
+ * os_strdup - Duplicate a string
+ * @s: Source string
+ * Returns: Allocated buffer with the string copied into it or %NULL on failure
+ *
+ * Caller is responsible for freeing the returned buffer with os_free().
+ */
+char *os_strdup(const char *s);
+
+/**
+ * os_strlen - Calculate the length of a string
+ * @s: '\0' terminated string
+ * Returns: Number of characters in s (not counting the '\0' terminator)
+ */
+size_t os_strlen(const char *s);
+
+/**
+ * os_strcasecmp - Compare two strings ignoring case
+ * @s1: First string
+ * @s2: Second string
+ * Returns: An integer less than, equal to, or greater than zero if s1 is
+ * found to be less than, to match, or be greatred than s2
+ */
+int os_strcasecmp(const char *s1, const char *s2);
+
+/**
+ * os_strncasecmp - Compare two strings ignoring case
+ * @s1: First string
+ * @s2: Second string
+ * @n: Maximum numbers of characters to compare
+ * Returns: An integer less than, equal to, or greater than zero if s1 is
+ * found to be less than, to match, or be greater than s2. Only first n
+ * characters will be compared.
+ */
+int os_strncasecmp(const char *s1, const char *s2, size_t n);
+
+/**
+ * os_strchr - Locate the first occurrence of a character in string
+ * @s: String
+ * @c: Character to search for
+ * Returns: Pointer to the matched character or %NULL if not found
+ */
+char *os_strchr(const char *s, int c);
+
+/**
+ * os_strrchr - Locate the last occurrence of a character in string
+ * @s: String
+ * @c: Character to search for
+ * Returns: Pointer to the matched character or %NULL if not found
+ */
+char *os_strrchr(const char *s, int c);
+
+/**
+ * os_strcmp - Compare two strings
+ * @s1: First string
+ * @s2: Second string
+ * Returns: An integer less than, equal to, or greater than zero if s1 is
+ * found to be less than, to match, or be greatred than s2
+ */
+int os_strcmp(const char *s1, const char *s2);
+
+/**
+ * os_strncmp - Compare two strings
+ * @s1: First string
+ * @s2: Second string
+ * @n: Maximum numbers of characters to compare
+ * Returns: An integer less than, equal to, or greater than zero if s1 is
+ * found to be less than, to match, or be greater than s2. Only first n
+ * characters will be compared.
+ */
+int os_strncmp(const char *s1, const char *s2, size_t n);
+
+/**
+ * os_strncpy - Copy a string
+ * @dest: Destination
+ * @src: Source
+ * @n: Maximum number of characters to copy
+ * Returns: dest
+ */
+char *os_strncpy(char *dest, const char *src, size_t n);
+
+/**
+ * os_strstr - Locate a substring
+ * @haystack: String (haystack) to search from
+ * @needle: Needle to search from haystack
+ * Returns: Pointer to the beginning of the substring or %NULL if not found
+ */
+char *os_strstr(const char *haystack, const char *needle);
+
+/**
+ * os_snprintf - Print to a memory buffer
+ * @str: Memory buffer to print into
+ * @size: Maximum length of the str buffer
+ * @format: printf format
+ * Returns: Number of characters printed (not including trailing '\0').
+ *
+ * If the output buffer is truncated, number of characters which would have
+ * been written is returned. Since some C libraries return -1 in such a case,
+ * the caller must be prepared on that value, too, to indicate truncation.
+ *
+ * Note: Some C library implementations of snprintf() may not guarantee null
+ * termination in case the output is truncated. The OS wrapper function of
+ * os_snprintf() should provide this guarantee, i.e., to null terminate the
+ * output buffer if a C library version of the function is used and if that
+ * function does not guarantee null termination.
+ *
+ * If the target system does not include snprintf(), see, e.g.,
+ * http://www.ijs.si/software/snprintf/ for an example of a portable
+ * implementation of snprintf.
+ */
+int os_snprintf(char *str, size_t size, const char *format, ...);
+
+#else /* OS_NO_C_LIB_DEFINES */
+
+#if !defined(CONFIG_PLATFORM_8195A) && !defined(CONFIG_PLATFORM_8711B)
+#ifdef CONFIG_MEM_MONITOR
+ uint8_t* os_malloc(uint32_t sz);
+ void os_mfree(uint8_t *pbuf, uint32_t sz);
+ #ifndef os_free
+ #define os_free(p, sz) os_mfree(((uint8_t*)(p)), (sz))
+ #endif
+#else
+ #ifndef os_malloc
+ #define os_malloc(sz) _rtw_malloc(sz)
+ #endif
+ #ifndef os_free
+ #define os_free(p, sz) _rtw_mfree(((uint8_t*)(p)), (sz))
+ #endif
+#endif
+#endif
+ extern void *os_zalloc(size_t size);
+ extern char *os_strdup(const char *string_copy_from);
+
+ #ifndef os_sleep
+ #define os_sleep(s, us) rtw_mdelay_os((s)*1000 + (us)/1000)
+ #endif
+ #ifndef os_memcpy
+ #define os_memcpy(d, s, n) rtw_memcpy((void*)(d), ((void*)(s)), (n))
+ #endif
+ #ifndef os_memmove
+ #define os_memmove(d, s, n) memmove((d), (s), (n))
+ #endif
+ #ifndef os_memset
+ #define os_memset(pbuf, c, sz) rtw_memset(pbuf, c, sz)
+ #endif
+ #ifndef os_memcmp
+ #define os_memcmp(s1, s2, n) rtw_memcmp(((void*)(s1)), ((void*)(s2)), (n))
+ #endif
+ #ifndef os_memcmp_p2p
+ #define os_memcmp_p2p(s1, s2, n) memcmp((s1), (s2), (n))
+ #endif
+ #ifndef os_get_random_bytes
+ #define os_get_random_bytes(d,sz) rtw_get_random_bytes(((void*)(d)), (sz))
+ #endif
+ #ifndef os_strlen
+ #define os_strlen(s) strlen(s)
+ #endif
+ #ifndef os_strcasecmp
+ #ifdef _MSC_VER
+ #define os_strcasecmp(s1, s2) _stricmp((s1), (s2))
+ #else
+ #define os_strcasecmp(s1, s2) strcasecmp((s1), (s2))
+ #endif
+ #endif
+ #ifndef os_strncasecmp
+ #ifdef _MSC_VER
+ #define os_strncasecmp(s1, s2, n) _strnicmp((s1), (s2), (n))
+ #else
+ #define os_strncasecmp(s1, s2, n) strncasecmp((s1), (s2), (n))
+ #endif
+ #endif
+ #ifndef os_init_timer
+ #define os_init_timer(t, p, f, x, n) rtw_init_timer((t), (p), (f), (x), (n))
+ #endif
+ #ifndef os_set_timer
+ #define os_set_timer(t, d) rtw_set_timer((t), (d))
+ #endif
+ #ifndef os_cancel_timer
+ #define os_cancel_timer(t) rtw_cancel_timer(t)
+ #endif
+ #ifndef os_del_timer
+ #define os_del_timer(t) rtw_del_timer(t)
+ #endif
+ #ifndef os_atoi
+ #define os_atoi(s) rtw_atoi(s)
+ #endif
+
+#ifndef os_strchr
+#define os_strchr(s, c) strchr((s), (c))
+#endif
+#ifndef os_strcmp
+#define os_strcmp(s1, s2) strcmp((s1), (s2))
+#endif
+#ifndef os_strncmp
+#define os_strncmp(s1, s2, n) strncmp((s1), (s2), (n))
+#endif
+#ifndef os_strncpy
+#define os_strncpy(d, s, n) strncpy((d), (s), (n))
+#endif
+#ifndef os_strrchr
+#define os_strrchr(s, c) strrchr((s), (c))
+#endif
+#ifndef os_strstr
+#define os_strstr(h, n) strstr((h), (n))
+#endif
+
+#ifndef os_snprintf
+ #ifdef _MSC_VER
+ #define os_snprintf _snprintf
+ #else
+ #define os_snprintf snprintf
+ #endif
+#endif
+
+#endif /* OS_NO_C_LIB_DEFINES */
+
+
+static inline void * os_realloc_array(void *ptr, size_t nmemb, size_t size)
+{
+ if (size && nmemb > (~(size_t) 0) / size)
+ return NULL;
+ return os_realloc(ptr, nmemb * size, nmemb * size);
+}
+
+void *os_xqueue_create(unsigned long uxQueueLength, unsigned long uxItemSize) ;
+
+int os_xqueue_receive(xqueue_handle_t xQueue, void * const pvBuffer, unsigned long xSecsToWait);
+
+void os_xqueue_delete(xqueue_handle_t xQueue );
+
+int os_xqueue_send(xqueue_handle_t xQueue, const void * const pvItemToQueue, unsigned long xSecsToWait);
+
+
+#endif /* OS_H */
diff --git a/RTLGDB/Project/rtl8195a/queue.h b/RTLGDB/Project/rtl8195a/queue.h
new file mode 100644
index 0000000..a760c8d
--- /dev/null
+++ b/RTLGDB/Project/rtl8195a/queue.h
@@ -0,0 +1,204 @@
+#ifndef _SYS_QUEUE_H_
+#define _SYS_QUEUE_H_
+
+#define QMD_SAVELINK(name, link)
+#define TRASHIT(x)
+
+/*
+ * Singly-linked List declarations.
+ */
+#define SLIST_HEAD(name, type) \
+struct name { \
+ struct type *slh_first; /* first element */ \
+}
+
+#define SLIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define SLIST_ENTRY(type) \
+struct { \
+ struct type *sle_next; /* next element */ \
+}
+
+/*
+ * Singly-linked List functions.
+ */
+#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
+
+#define SLIST_FIRST(head) ((head)->slh_first)
+
+#define SLIST_FOREACH(var, head, field) \
+ for ((var) = SLIST_FIRST((head)); \
+ (var); \
+ (var) = SLIST_NEXT((var), field))
+
+#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = SLIST_FIRST((head)); \
+ (var) && ((tvar) = SLIST_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
+ for ((varp) = &SLIST_FIRST((head)); \
+ ((var) = *(varp)) != NULL; \
+ (varp) = &SLIST_NEXT((var), field))
+
+#define SLIST_INIT(head) do { \
+ SLIST_FIRST((head)) = NULL; \
+} while (0)
+
+#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
+ SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
+ SLIST_NEXT((slistelm), field) = (elm); \
+} while (0)
+
+#define SLIST_INSERT_HEAD(head, elm, field) do { \
+ SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
+ SLIST_FIRST((head)) = (elm); \
+} while (0)
+
+#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
+
+#define SLIST_REMOVE(head, elm, type, field) do { \
+ QMD_SAVELINK(oldnext, (elm)->field.sle_next); \
+ if (SLIST_FIRST((head)) == (elm)) { \
+ SLIST_REMOVE_HEAD((head), field); \
+ } \
+ else { \
+ struct type *curelm = SLIST_FIRST((head)); \
+ while (SLIST_NEXT(curelm, field) != (elm)) \
+ curelm = SLIST_NEXT(curelm, field); \
+ SLIST_REMOVE_AFTER(curelm, field); \
+ } \
+ TRASHIT(*oldnext); \
+} while (0)
+
+#define SLIST_REMOVE_AFTER(elm, field) do { \
+ SLIST_NEXT(elm, field) = \
+ SLIST_NEXT(SLIST_NEXT(elm, field), field); \
+} while (0)
+
+#define SLIST_REMOVE_HEAD(head, field) do { \
+ SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
+} while (0)
+
+/*
+ * Singly-linked Tail queue declarations.
+ */
+#define STAILQ_HEAD(name, type) \
+ struct name { \
+ struct type *stqh_first;/* first element */ \
+ struct type **stqh_last;/* addr of last next element */ \
+ }
+
+#define STAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).stqh_first }
+
+#define STAILQ_ENTRY(type) \
+ struct { \
+ struct type *stqe_next; /* next element */ \
+ }
+
+/*
+ * Singly-linked Tail queue functions.
+ */
+#define STAILQ_CONCAT(head1, head2) do { \
+ if (!STAILQ_EMPTY((head2))) { \
+ *(head1)->stqh_last = (head2)->stqh_first; \
+ (head1)->stqh_last = (head2)->stqh_last; \
+ STAILQ_INIT((head2)); \
+ } \
+ } while (0)
+
+#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
+
+#define STAILQ_FIRST(head) ((head)->stqh_first)
+
+#define STAILQ_FOREACH(var, head, field) \
+ for((var) = STAILQ_FIRST((head)); \
+ (var); \
+ (var) = STAILQ_NEXT((var), field))
+
+
+#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = STAILQ_FIRST((head)); \
+ (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#define STAILQ_INIT(head) do { \
+ STAILQ_FIRST((head)) = NULL; \
+ (head)->stqh_last = &STAILQ_FIRST((head)); \
+ } while (0)
+
+#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
+ if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+ STAILQ_NEXT((tqelm), field) = (elm); \
+ } while (0)
+
+#define STAILQ_INSERT_HEAD(head, elm, field) do { \
+ if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+ STAILQ_FIRST((head)) = (elm); \
+ } while (0)
+
+#define STAILQ_INSERT_TAIL(head, elm, field) do { \
+ STAILQ_NEXT((elm), field) = NULL; \
+ *(head)->stqh_last = (elm); \
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+ } while (0)
+
+#define STAILQ_LAST(head, type, field) \
+ (STAILQ_EMPTY((head)) ? \
+ NULL : \
+ ((struct type *)(void *) \
+ ((char *)((head)->stqh_last) - __offsetof(struct type, field))))
+
+#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
+
+#define STAILQ_REMOVE(head, elm, type, field) do { \
+ QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \
+ if (STAILQ_FIRST((head)) == (elm)) { \
+ STAILQ_REMOVE_HEAD((head), field); \
+ } \
+ else { \
+ struct type *curelm = STAILQ_FIRST((head)); \
+ while (STAILQ_NEXT(curelm, field) != (elm)) \
+ curelm = STAILQ_NEXT(curelm, field); \
+ STAILQ_REMOVE_AFTER(head, curelm, field); \
+ } \
+ TRASHIT(*oldnext); \
+ } while (0)
+
+#define STAILQ_REMOVE_HEAD(head, field) do { \
+ if ((STAILQ_FIRST((head)) = \
+ STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
+ (head)->stqh_last = &STAILQ_FIRST((head)); \
+ } while (0)
+
+#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
+ if ((STAILQ_NEXT(elm, field) = \
+ STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+ } while (0)
+
+#define STAILQ_SWAP(head1, head2, type) do { \
+ struct type *swap_first = STAILQ_FIRST(head1); \
+ struct type **swap_last = (head1)->stqh_last; \
+ STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \
+ (head1)->stqh_last = (head2)->stqh_last; \
+ STAILQ_FIRST(head2) = swap_first; \
+ (head2)->stqh_last = swap_last; \
+ if (STAILQ_EMPTY(head1)) \
+ (head1)->stqh_last = &STAILQ_FIRST(head1); \
+ if (STAILQ_EMPTY(head2)) \
+ (head2)->stqh_last = &STAILQ_FIRST(head2); \
+ } while (0)
+
+#define STAILQ_INSERT_CHAIN_HEAD(head, elm_chead, elm_ctail, field) do { \
+ if ((STAILQ_NEXT(elm_ctail, field) = STAILQ_FIRST(head)) == NULL ) { \
+ (head)->stqh_last = &STAILQ_NEXT(elm_ctail, field); \
+ } \
+ STAILQ_FIRST(head) = (elm_chead); \
+ } while (0)
+
+#endif /* !_SYS_QUEUE_H_ */
diff --git a/RTLGDB/Project/rtl8195a/rom_wps_os.h b/RTLGDB/Project/rtl8195a/rom_wps_os.h
new file mode 100644
index 0000000..5bb6da5
--- /dev/null
+++ b/RTLGDB/Project/rtl8195a/rom_wps_os.h
@@ -0,0 +1,24 @@
+/*
+ * OS specific functions
+ * Copyright (c) 2005-2009, Jouni Malinen
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef ROM_WPS_OS_H
+#define ROM_WPS_OS_H
+
+#if defined(CONFIG_PLATFORM_8195A) || defined(CONFIG_PLATFORM_8711B)
+
+#include
+extern struct _rom_wlan_ram_map rom_wlan_ram_map;
+#define os_malloc(sz) rom_wlan_ram_map.rtw_malloc(sz)
+#define os_free(p, sz) rom_wlan_ram_map.rtw_mfree(((uint8_t*)(p)), (sz))
+
+#endif
+
+extern uint8_t *WPS_realloc(uint8_t *old_buf, uint32_t old_sz, uint32_t new_sz);
+#define os_realloc(p, os, ns) WPS_realloc(((uint8_t*)(p)),(os),(ns))
+
+#endif /* ROM_WPS_OS_H */
diff --git a/RTLGDB/Project/rtl8195a/rtl_common.h b/RTLGDB/Project/rtl8195a/rtl_common.h
new file mode 100644
index 0000000..a107e16
--- /dev/null
+++ b/RTLGDB/Project/rtl8195a/rtl_common.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C)
+ *
+ */
+
+#ifndef __RTL_COMMON_H__
+#define __RTL_COMMON_H__
+
+#include
+#include
+#include
+
+#include "c_types.h"
+
+#endif
diff --git a/RTLGDB/Project/rtl8195a/rtl_libc.h b/RTLGDB/Project/rtl8195a/rtl_libc.h
new file mode 100644
index 0000000..40a9699
--- /dev/null
+++ b/RTLGDB/Project/rtl8195a/rtl_libc.h
@@ -0,0 +1,164 @@
+/*
+* ROM calls
+*/
+
+#ifndef _INC_RTL_LIBC_
+#define _INC_RTL_LIBC_
+
+#undef malloc
+#define malloc(size) pvPortMalloc(size)
+#undef free
+#define free(pbuf) vPortFree(pbuf)
+
+#define atoi(str) prvAtoi(str)
+
+#define calloc(nelements, elementSize) calloc_freertos(nelements, elementSize)
+
+#define snprintf rtl_snprintf
+#define sprintf rtl_sprintf
+#define printf rtl_printf
+#define vprintf rtl_vprintf
+#define vsnprintf rtl_vsnprintf
+#define vfprintf rtl_vfprintf
+#define memchr rtl_memchr
+#define memcmp rtl_memcmp
+#define memcpy rtl_memcpy
+#define memmove rtl_memmove
+#define memset rtl_memset
+#define strcat rtl_strcat
+#define strchr rtl_strchr
+#define strcmp rtl_strcmp
+#define strcpy rtl_strcpy
+#define strlen rtl_strlen
+#define strncat rtl_strncat
+#define strncmp rtl_strncmp
+#define strncpy rtl_strncpy
+#define strstr rtl_strstr
+#define strsep rtl_strsep
+#define strtok rtl_strtok
+
+#define dtoi rtl_dtoi
+#define dtoui rtl_dtoui
+#define i2f rtl_i2f
+#define i2d rtl_i2d
+#define ui2f rtl_ui2f
+#define ui2d rtl_ui2d
+#define itoa rtl_itoa
+#define ltoa rtl_ltoa
+#define utoa rtl_utoa
+#define ultoa rtl_ultoa
+#define ftol rtl_ftol
+#define ftod rtl_ftod
+#define dtof rtl_dtof
+#define fadd rtl_fadd
+#define fsub rtl_fsub
+#define fmul rtl_fmul
+#define fdiv rtl_fdiv
+#define dadd rtl_dadd
+#define dsub rtl_dsub
+#define dmul rtl_dmul
+#define ddiv rtl_ddiv
+#define dcmpeq rtl_dcmpeq
+#define dcmplt rtl_dcmplt
+#define dcmple rtl_dcmple
+#define dcmpgt rtl_dcmpgt
+#define fcmplt rtl_fcmplt
+#define fcmpgt rtl_fcmpgt
+
+#define fabsf rtl_fabsf
+#define fabs rtl_fabs
+#define cos_f32 rtl_cos_f32
+#define sin_f32 rtl_sin_f32
+
+
+#if 0
+extern void *calloc_freertos(size_t nelements, size_t elementSize);
+// ram_libc.c
+extern int rtl_snprintf(char *str, size_t size, const char *fmt, ...);
+extern int rtl_sprintf(char *str, const char *fmt, ...);
+extern int rtl_printf(const char *fmt, ...);
+extern int rtl_vprintf(const char *fmt, void *param);
+extern int rtl_vsnprintf(char *str, size_t size, const char *fmt, void *param);
+extern int rtl_vfprintf(FILE *fp, const char *fmt0, va_list ap);
+extern int rtl_memchr(const void *src_void, int c, size_t length);
+extern int rtl_memcmp(const void *m1, const void *m2, size_t n);
+extern int rtl_memcpy(void *dst0, const void *src0, size_t len0);
+extern int rtl_memmove(void *dst_void, const void *src_void, size_t length);
+extern int rtl_memset(void *m, int c, size_t n);
+extern char * rtl_strcat(char *s1, const char *s2);
+extern char * rtl_strchr(const char *s1, int i);
+extern int rtl_strcmp(const char *s1, const char *s2);
+extern char * rtl_strcpy(char *dst0, const char *src0);
+extern int rtl_strlen(const char *str);
+extern char * rtl_strncat(char *s1, const char *s2, size_t n);
+extern int rtl_strncmp(const char *s1, const char *s2, size_t n);
+extern char * rtl_strncpy(char *dst0, const char *src0, size_t count);
+extern char * rtl_strstr(const char *searchee, const char *lookfor);
+extern char * rtl_strsep(char **source_ptr, const char *delim);
+extern char * rtl_strtok(char *s, const char *delim);
+
+//rtl_eabi_cast_ram.c
+extern int rtl_dtoi(double d);
+extern int rtl_dtoui(double d);
+extern float rtl_i2f(int val);
+extern int rtl_i2d(int val);
+extern float rtl_ui2f(unsigned int val);
+extern int rtl_ui2d(unsigned int val);
+extern char *rtl_itoa(int value, char *string, int radix);
+extern char *rtl_ltoa(int value, char *string, int radix);
+extern char *rtl_utoa(unsigned int value, char *string, int radix);
+extern char *rtl_ultoa(unsigned int value, char *string, int radix);
+extern int rtl_ftol(float f);
+extern int rtl_ftod(float f);
+extern float rtl_dtof(double d);
+extern float rtl_fadd(float a, float b);
+extern float rtl_fsub(float a, float b);
+extern float rtl_fmul(float a, float b);
+extern float rtl_fdiv(float a, float b);
+extern int rtl_dadd(double a, double b);
+extern int rtl_dsub(double a, double b);
+extern int rtl_dmul(double a, double b);
+extern int rtl_ddiv(double a, double b);
+extern int rtl_dcmpeq(double a, double b);
+extern int rtl_dcmplt(double a, double b);
+extern int rtl_dcmple(double a, double b);
+extern int rtl_dcmpgt(double a, double b);
+extern int rtl_fcmplt(float a, float b);
+extern int rtl_fcmpgt(float a, float b);
+
+// rtl_math_ram.c
+extern float rtl_fabsf(float a);
+extern int rtl_fabs(double a);
+extern float rtl_cos_f32(float a);
+extern float rtl_sin_f32(float a);
+
+// ram_pvvx_libc.c
+extern int snprintf(char *str, size_t size, const char *fmt, ...);
+extern int sprintf(char *str, const char *fmt, ...);
+extern int printf(const char *fmt, ...);
+extern int vprintf(const char *fmt, void *param);
+extern int vsnprintf(char *str, size_t size, const char *fmt, void *param);
+extern int vfprintf(FILE *fp, const char *fmt0, va_list ap);
+extern int memchr(const void *src_void, int c, size_t length);
+extern int memcmp(const void *m1, const void *m2, size_t n);
+extern int memcpy(void *dst0, const void *src0, size_t len0);
+extern int memmove(void *dst_void, const void *src_void, size_t length);
+extern int memset(void *m, int c, size_t n);
+extern char * strcat(char *s1, const char *s2);
+extern char * strchr(const char *s1, int i);
+extern int strcmp(const char *s1, const char *s2);
+extern char * strcpy(char *dst0, const char *src0);
+extern int strlen(const char *str);
+extern char * strncat(char *s1, const char *s2, size_t n);
+extern int strncmp(const char *s1, const char *s2, size_t n);
+extern char * strncpy(char *dst0, const char *src0, size_t count);
+extern char * strstr(const char *searchee, const char *lookfor);
+extern char * strsep(char **source_ptr, const char *delim);
+extern char * strtok(char *s, const char *delim);
+extern int sscanf(const char *buf, const char *fmt, ...);
+extern char toupper(char ch);
+extern int _stricmp (const char *s1, const char *s2);
+extern unsigned long long __aeabi_llsr(unsigned long long val, unsigned int shift);
+#endif
+
+#endif // _INC_RTL_LIBC_
diff --git a/RTLGDB/Project/sys_cfg.h b/RTLGDB/Project/sys_cfg.h
new file mode 100644
index 0000000..904fe3b
--- /dev/null
+++ b/RTLGDB/Project/sys_cfg.h
@@ -0,0 +1,67 @@
+/*
+ * sys_cfg.h
+ *
+ * Created on: 17/04/17
+ * Author: pvvx
+ */
+#ifndef __SYS_CFG_H__
+#define __SYS_CFG_H__
+#include "user_config.h"
+#define FEEP_ID_SYS_CFG 0x5359
+
+struct sys_bits_config {
+ uint16 powersave_enable : 1; //0 0x0000001 =1 Включение режима экономии энергии (актуально в режиме ST), отключает LogUART
+ uint16 pin_clear_cfg_enable : 1; //1 0x0000002 =1 Проверять ножку RX на сброс конфигурации WiFi
+ uint16 debug_print_enable : 1; //2 0x0000004 =1 Вывод отладочной информации на GPIO2
+ uint16 web_time_wait_delete : 1; //3 0x0000008 =1 Закрывать соединение и убивать pcb c TIME_WAIT
+ uint16 netbios_ena : 1; //4 0x0000010 =1 включить NetBios
+ uint16 sntp_ena : 1; //5 0x0000020 =1 включить SNTP
+ uint16 cdns_ena : 1; //6 0x0000040 =1 включить CAPDNS
+ uint16 tcp2uart_reopen : 1; //7 0x0000080 =1 открытие нового соединения tcp2uart ведет к закрытию старого соединения (в режиме tcp2uart = сервер)
+ uint16 mdb_reopen : 1; //8 0x0000100 =1 открытие нового соединения modbus ведет к закрытию старого соединения (в режиме modbus = сервер)
+};
+
+#define SYS_CFG_POWERSAVE 0x0000001 // Включение режима экономии энергии (актуально в режиме ST)
+#define SYS_CFG_PIN_CLR_ENA 0x0000002 // Проверять ножку RX на сброс конфигурации WiFi
+#define SYS_CFG_DEBUG_ENA 0x0000004 // Вывод отладочной информации на GPIO2
+#define SYS_CFG_TWPCB_DEL 0x0000008 // Закрывать соединение и убивать pcb c TIME_WAIT
+#define SYS_CFG_NETBIOS_ENA 0x0000010 // включить NetBios
+#define SYS_CFG_SNTP_ENA 0x0000020 // включить SNTP
+#define SYS_CFG_CDNS_ENA 0x0000040 // включить CAPDNS
+#define SYS_CFG_T2U_REOPEN 0x0000080 // открытие нового соединения tcp2uart ведет к закрытию старого соединения (сервер)
+#define SYS_CFG_MDB_REOPEN 0x0000100 // открытие нового соединения modbus ведет к закрытию старого соединения (сервер)
+
+
+struct SystemCfg
+{ // структура сохранения системных настроек в Flash
+ union
+ {
+ struct sys_bits_config b;
+ uint16 w;
+ } cfg;
+
+ uint16 tcp_client_twait; // время (миллисек) до повтора соединения клиента
+#ifdef USE_TCP2UART
+ uint16 tcp2uart_port; // номер порта TCP-UART (=0 - отключен)
+ uint16 tcp2uart_twrec; // время (сек) стартового ожидания приема/передачи первого пакета, до авто-закрытия соединения
+ uint16 tcp2uart_twcls; // время (сек) до авто-закрытия соединения после приема или передачи
+#endif
+#ifdef USE_WEB
+ uint16 web_port; // номер порта WEB (=0 - отключен)
+ uint16 web_twrec; // время (сек) стартового ожидания приема/передачи первого пакета, до авто-закрытия соединения
+ uint16 web_twcls; // время (сек) до авто-закрытия соединения после приема или передачи
+#endif
+#ifdef USE_MODBUS
+ uint16 mdb_port; // =0 - отключен
+ uint16 mdb_twrec; // время (сек) стартового ожидания приема/передачи первого пакета, до авто-закрытия соединения
+ uint16 mdb_twcls; // время (сек) до авто-закрытия соединения после приема или передачи
+ uint8 mdb_id; // номер устройства ESP8266 по шине modbus
+#endif
+} __attribute__((packed));
+
+
+extern void sys_write_cfg(void);
+
+extern struct SystemCfg syscfg;
+
+#endif // #define __SYS_CFG_H__
diff --git a/RTLGDB/Project/tcpsrv/tcp_srv_conn.c b/RTLGDB/Project/tcpsrv/tcp_srv_conn.c
new file mode 100644
index 0000000..c1b7d07
--- /dev/null
+++ b/RTLGDB/Project/tcpsrv/tcp_srv_conn.c
@@ -0,0 +1,1013 @@
+/******************************************************************************
+ * FileName: tcp_srv_conn.c
+ * TCP сервачек для ESP8266
+ * pvvx ver1.0 20/12/2014
+ * Перекинут на RTL871X pvvx 2017
+ ******************************************************************************/
+#include "user_config.h"
+#include "autoconf.h"
+#include "FreeRTOS.h"
+#include "task.h"
+#include "diag.h"
+#include "lwip/tcp.h"
+#include "lwip/tcp_impl.h"
+#include "lwip/memp.h"
+#include "lwip/ip_addr.h"
+#include "flash_eep.h"
+#include "tcpsrv/tcp_srv_conn.h"
+#include "rtl8195a/rtl_libc.h"
+#include "esp_comp.h"
+
+#ifdef CONFIG_DEBUG_LOG
+#undef DEBUGSOO
+#define DEBUGSOO 2 // уровень вывода отладочной инфы по умолчанию = 2, =1 только error
+#else
+#undef DEBUGSOO
+#define DEBUGSOO 0
+#endif
+// Lwip funcs - http://www.ecoscentric.com/ecospro/doc/html/ref/lwip.html
+
+#define TCP_SRV_BSSDATA_ATTR
+#define TCP_SRV_RODATA_ATTR
+#define TCP_SRV_CODE_ATTR
+
+#define ts_printf(...) rtl_printf(__VA_ARGS__)
+#define system_get_free_heap_size xPortGetFreeHeapSize
+
+extern void *pvPortZalloc(size_t xWantedSize);
+extern void vPortFree(void *pv);
+extern void *pvPortMalloc(size_t xWantedSize);
+#undef os_free
+#define os_free(p) vPortFree(p)
+#undef os_malloc
+#define os_malloc(p) pvPortMalloc(p)
+#undef os_zalloc
+#define os_zalloc(p) pvPortZalloc(p)
+#undef os_realloc
+#define os_realloc(p,s) pvPortReAlloc(p,s)
+/*
+extern __rtl_memsetw_v1_00(void *, uint32, size_t);
+
+void *pvPortZalloc( size_t xWantedSize )
+{
+ void *pvReturn = pvPortMalloc(xWantedSize);
+ if(pvReturn != NULL) __rtl_memsetw_v1_00(pvReturn, 0, (xWantedSize + 3)>>2);
+ return pvReturn;
+}
+*/
+
+TCP_SERV_CFG *phcfg TCP_SRV_BSSDATA_ATTR; // = NULL; // начальный указатель в памяти на структуры открытых сервачков
+
+#if DEBUGSOO > 0
+const uint8 txt_tcpsrv_NULL_pointer[] TCP_SRV_RODATA_ATTR = "tcpsrv: NULL pointer!\n";
+const uint8 txt_tcpsrv_already_initialized[] TCP_SRV_RODATA_ATTR = "tcpsrv: already initialized!\n";
+const uint8 txt_tcpsrv_out_of_mem[] TCP_SRV_RODATA_ATTR = "tcpsrv: out of mem!\n";
+#endif
+
+//#define mMIN(a, b) ((a -16) && (err < 1)) {
+ return lwip_strerr(err);
+ }
+ else return srvContenErrX;
+}
+
+extern const char * const tcp_state_str[];
+/******************************************************************************
+ * FunctionName : tspsrv_tcp_state_msg
+ * Description : строка tcp_state по номеру
+ * Parameters : LwIP tcp_state
+ * Returns : указатель на строку
+ *******************************************************************************/
+const char * tspsrv_tcp_state_msg(enum tcp_state state)
+{
+ if(state > TIME_WAIT && state < CLOSED) return srvContenErrX;
+ return tcp_state_str[state];
+}
+/******************************************************************************
+ * FunctionName : tspsrv_tcp_state_msg
+ * Description : строка tcp_state по номеру
+ * Parameters : LwIP tcp_state
+ * Returns : указатель на строку
+ *******************************************************************************/
+static const char *msg_srvconn_state[] = {
+ "NONE",
+ "CLOSEWAIT",
+ "LISTEN",
+ "CONNECT",
+ "CLOSED"
+};
+
+const char * tspsrv_srvconn_state_msg(enum srvconn_state state)
+{
+ if(state > SRVCONN_CLOSED && state < SRVCONN_NONE) return (const char *) srvContenErrX;
+ return (const char *) msg_srvconn_state[state];
+}
+//#endif
+/******************************************************************************
+ * FunctionName : tcpsrv_print_remote_info
+ * Description : выводит remote_ip:remote_port [conn_count] ts_printf("srv x.x.x.x:x [n] ")
+ * Parameters : TCP_SERV_CONN * ts_conn
+ * Returns : none
+ *******************************************************************************/
+void TCP_SRV_CODE_ATTR tcpsrv_print_remote_info(TCP_SERV_CONN *ts_conn) {
+//#if DEBUGSOO > 0
+ uint16 port;
+ if(ts_conn->pcb != NULL) port = ts_conn->pcb->local_port;
+ else port = ts_conn->pcfg->port;
+ ts_printf("srv[%u] %d.%d.%d.%d:%d [%d] ", port,
+ ts_conn->remote_ip.b[0], ts_conn->remote_ip.b[1],
+ ts_conn->remote_ip.b[2], ts_conn->remote_ip.b[3],
+ ts_conn->remote_port, ts_conn->pcfg->conn_count);
+//#endif
+}
+/******************************************************************************
+ * Default call back functions
+ ******************************************************************************/
+//------------------------------------------------------------------------------
+void TCP_SRV_CODE_ATTR tcpsrv_disconnect_calback_default(TCP_SERV_CONN *ts_conn) {
+ ts_conn->pcb = NULL;
+#if DEBUGSOO > 1
+ tcpsrv_print_remote_info(ts_conn);
+ ts_printf("disconnect\n");
+#endif
+}
+//------------------------------------------------------------------------------
+err_t TCP_SRV_CODE_ATTR tcpsrv_listen_default(TCP_SERV_CONN *ts_conn) {
+#if DEBUGSOO > 1
+ tcpsrv_print_remote_info(ts_conn);
+ ts_printf("listen\n");
+#endif
+ return ERR_OK;
+}
+//------------------------------------------------------------------------------
+err_t TCP_SRV_CODE_ATTR tcpsrv_connected_default(TCP_SERV_CONN *ts_conn) {
+#if DEBUGSOO > 1
+ tcpsrv_print_remote_info(ts_conn);
+ ts_printf("connected\n");
+#endif
+ return ERR_OK;
+}
+//------------------------------------------------------------------------------
+err_t TCP_SRV_CODE_ATTR tcpsrv_sent_callback_default(TCP_SERV_CONN *ts_conn) {
+#if DEBUGSOO > 1
+ tcpsrv_print_remote_info(ts_conn);
+ ts_printf("sent_cb\n");
+#endif
+ return ERR_OK;
+}
+//------------------------------------------------------------------------------
+err_t TCP_SRV_CODE_ATTR tcpsrv_received_data_default(TCP_SERV_CONN *ts_conn) {
+#if DEBUGSOO > 1
+ tcpsrv_print_remote_info(ts_conn);
+ ts_printf("received, buffer %d bytes\n", ts_conn->sizei);
+#endif
+ return ERR_OK;
+}
+/******************************************************************************
+ * FunctionName : tcpsrv_check_max_tm_tcp_pcb
+ * Description : Ограничение неактивных pcb в списках lwip до MAX_TIME_WAIT_PCB
+ * Parameters : none
+ * Returns : none
+ *******************************************************************************/
+static void TCP_SRV_CODE_ATTR tcpsrv_check_max_tm_tcp_pcb(void)
+{
+ struct tcp_pcb *pcb;
+ int i = 0;
+ for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) i++;
+#if DEBUGSOO > 4
+ ts_printf("tcpsrv: check %d tm pcb\n", i);
+#endif
+ while(i-- > MAX_TIME_WAIT_PCB) {
+ struct tcp_pcb *inactive = NULL;
+ for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
+ inactive = pcb;
+ }
+#if DEBUGSOO > 3
+ ts_printf("tcpsrv: kill %d tm pcb\n", i);
+#endif
+ if(inactive != NULL) {
+ tcp_pcb_remove(&tcp_tw_pcbs, inactive);
+ memp_free(MEMP_TCP_PCB, inactive);
+ }
+ }
+}
+/******************************************************************************
+ * FunctionName : find_tcp_pcb
+ * Description : поиск pcb в списках lwip
+ * Parameters : TCP_SERV_CONN * ts_conn
+ * Returns : *pcb or NULL
+ *******************************************************************************/
+struct tcp_pcb * TCP_SRV_CODE_ATTR find_tcp_pcb(TCP_SERV_CONN * ts_conn) {
+ struct tcp_pcb *pcb = ts_conn->pcb;
+ if (pcb) {
+ uint16 remote_port = ts_conn->remote_port;
+ uint16 local_port = ts_conn->pcfg->port;
+ uint32 ip = ts_conn->remote_ip.dw;
+ if ((pcb->remote_port == remote_port) && (pcb->local_port == local_port)
+ && (pcb->remote_ip.addr == ip))
+ return pcb;
+ for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
+ if ((pcb->remote_port == remote_port) && (pcb->local_port == local_port)
+ && (pcb->remote_ip.addr == ip))
+ return pcb;
+ };
+ for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
+ if ((pcb->remote_port == remote_port) && (pcb->local_port == local_port)
+ && (pcb->remote_ip.addr == ip))
+ return pcb;
+ };
+ }
+ return NULL;
+}
+/******************************************************************************
+ * FunctionName : tcpsrv_disconnect
+ * Description : disconnect
+ * Parameters : TCP_SERV_CONN * ts_conn
+ * Returns : none
+ *******************************************************************************/
+void TCP_SRV_CODE_ATTR tcpsrv_disconnect(TCP_SERV_CONN * ts_conn) {
+ if (ts_conn == NULL || ts_conn->state == SRVCONN_CLOSEWAIT) return; // уже закрывается
+ ts_conn->pcb = find_tcp_pcb(ts_conn); // ещё жива данная pcb ?
+ if (ts_conn->pcb != NULL) tcpsrv_server_close(ts_conn);
+}
+/******************************************************************************
+ * FunctionName : internal fun: tcpsrv_int_sent_data
+ * Description : передача данных (не буферизированная! только передача в tcp Lwip-у)
+ * вызывать только из call back с текущим pcb!
+ * Parameters : TCP_SERV_CONN * ts_conn
+ * uint8* psent - буфер с данными
+ * uint16 length - кол-во передаваемых байт
+ * Returns : tcp error
+ ******************************************************************************/
+err_t TCP_SRV_CODE_ATTR tcpsrv_int_sent_data(TCP_SERV_CONN * ts_conn, uint8 *psent, uint16 length) {
+ err_t err = ERR_ARG;
+ if(ts_conn == NULL) return err;
+ ts_conn->pcb = find_tcp_pcb(ts_conn); // ещё жива данная pcb ?
+ struct tcp_pcb *pcb = ts_conn->pcb;
+ if(pcb == NULL || ts_conn->state == SRVCONN_CLOSEWAIT) return ERR_CONN;
+ ts_conn->flag.busy_bufo = 1; // буфер bufo занят
+ if(tcp_sndbuf(pcb) < length) {
+#if DEBUGSOO > 1
+ ts_printf("sent_data length (%u) > sndbuf (%u)!\n", length, tcp_sndbuf(pcb));
+#endif
+ return err;
+ }
+ if (length) {
+ if(ts_conn->flag.nagle_disabled) tcp_nagle_disable(pcb);
+ err = tcp_write(pcb, psent, length, 1);
+ if (err == ERR_OK) {
+ ts_conn->ptrtx = psent + length;
+ ts_conn->cntro -= length;
+ ts_conn->flag.wait_sent = 1; // ожидать завершения передачи (sent_cb)
+ err = tcp_output(pcb); // передать что влезло
+ } else { // ts_conn->state = SRVCONN_CLOSE;
+#if DEBUGSOO > 1
+ ts_printf("tcp_write(%p, %p, %u) = %d! pbuf = %u\n", pcb, psent, length, err, tcp_sndbuf(pcb));
+#endif
+ ts_conn->flag.wait_sent = 0;
+ tcpsrv_server_close(ts_conn);
+ };
+ } else { // создать вызов tcpsrv_server_sent()
+ tcp_nagle_enable(pcb);
+ err = tcp_output(pcb); // передать пустое
+ }
+ ts_conn->flag.busy_bufo = 0; // буфер bufo свободен
+ return err;
+}
+/******************************************************************************
+ * FunctionName : tcpsrv_server_sent
+ * Description : Data has been sent and acknowledged by the remote host.
+ * This means that more data can be sent.
+ * Parameters : arg -- Additional argument to pass to the callback function
+ * pcb -- The connection pcb for which data has been acknowledged
+ * len -- The amount of bytes acknowledged
+ * Returns : ERR_OK: try to send some data by calling tcp_output
+ * ERR_ABRT: if you have called tcp_abort from within the function!
+ ******************************************************************************/
+static err_t TCP_SRV_CODE_ATTR tcpsrv_server_sent(void *arg, struct tcp_pcb *pcb, uint16_t len) {
+ sint8 ret_err = ERR_OK;
+ TCP_SERV_CONN * ts_conn = arg;
+ if (ts_conn == NULL || pcb == NULL) return ERR_ARG;
+ ts_conn->state = SRVCONN_CONNECT;
+ ts_conn->recv_check = 0;
+ ts_conn->flag.wait_sent = 0; // блок передан
+ if ((ts_conn->flag.tx_null == 0)
+ && (ts_conn->pcfg->func_sent_cb != NULL)) {
+ ret_err = ts_conn->pcfg->func_sent_cb(ts_conn);
+ }
+ return ret_err;
+}
+/******************************************************************************
+ * FunctionName : recv_trim_bufi
+ * Description : увеличение размера буфера приема на newadd
+ * Parameters : ts_conn, newadd - требуемое дополнение размера буфера
+ * Returns : err_t
+ ******************************************************************************/
+static err_t TCP_SRV_CODE_ATTR recv_trim_bufi(TCP_SERV_CONN * ts_conn, uint32 newadd)
+{
+ uint32 len = 0;
+// while(ts_conn->flag.busy_bufi) vTaskDelay(1);
+ ts_conn->flag.busy_bufi = 1; // идет обработка bufi
+ if(newadd) {
+ // требуется дополнение размера буфера
+ if(ts_conn->pbufi != NULL) { // уже есть какой-то буфер
+ if ((ts_conn->flag.rx_buf) && ts_conn->cntri < ts_conn->sizei) { // буфер не пуст
+ len = ts_conn->sizei - ts_conn->cntri; // размер необработанных данных
+ if(ts_conn->cntri >= newadd) { // кол-во обработанных байт (пустого места в буфере) больше чем дополнение
+ os_memcpy(ts_conn->pbufi, &ts_conn->pbufi[ts_conn->cntri], len ); // скопировать необработанную часть в начало буфера
+ ts_conn->sizei = len;
+ if(ts_conn->cntri != newadd) { // кол-во обработанных байт (пустого места в буфере) равно требуемому дополнению
+ // уменьшение занимаемого буфера в памяти
+ len += newadd; //
+ ts_conn->pbufi = (uint8 *)os_realloc(ts_conn->pbufi, len + 1); //mem_trim(ts_conn->pbufi, len);
+ if(ts_conn->pbufi == NULL) {
+#if DEBUGSOO > 2
+ ts_printf("memtrim err %p[%d] ", ts_conn->pbufi, len + 1);
+#endif
+ return ERR_MEM;
+ }
+#if DEBUGSOO > 2
+ ts_printf("memi%p[%d] ", ts_conn->pbufi, len);
+#endif
+ }
+ ts_conn->pbufi[len] = '\0'; // вместо os_zalloc;
+ ts_conn->cntri = 0;
+ ts_conn->flag.busy_bufi = 0; // обработка bufi окончена
+ return ERR_OK;
+ }
+ }
+ else { // буфер пуст или не тот режим
+ // удалить буфер
+ os_free(ts_conn->pbufi);
+ ts_conn->pbufi = NULL;
+ }
+ }
+ // подготовка нового буфера, если его нет или не лезет дополнение
+ uint8 * newbufi = (uint8 *) os_malloc(len + newadd + 1);
+ if (newbufi == NULL) {
+#if DEBUGSOO > 2
+ ts_printf("memerr %p[%d] ", newbufi, len + newadd);
+#endif
+ ts_conn->flag.busy_bufi = 0; // обработка bufi окончена
+ return ERR_MEM;
+ }
+#if DEBUGSOO > 2
+ ts_printf("memi%p[%d] ", newbufi, len + newadd);
+#endif
+ newbufi[len + newadd] = '\0'; // вместо os_zalloc
+ if(len) {
+ os_memcpy(newbufi, &ts_conn->pbufi[ts_conn->cntri], len);
+ os_free(ts_conn->pbufi);
+ };
+ ts_conn->pbufi = newbufi;
+ ts_conn->sizei = len;
+ }
+ else {
+ // оптимизация буфера (уменьшение занимаемого размера)
+ if((!ts_conn->flag.rx_buf) || ts_conn->cntri >= ts_conn->sizei) { // буфер обработан
+ ts_conn->sizei = 0;
+ if (ts_conn->pbufi != NULL) {
+ os_free(ts_conn->pbufi); // освободить буфер.
+ ts_conn->pbufi = NULL;
+ };
+ }
+ else if(ts_conn->cntri) { // есть обработанные данные
+ // уменьшение занимаемого размера на обработанные данные
+ len = ts_conn->sizei - ts_conn->cntri;
+ os_memcpy(ts_conn->pbufi, &ts_conn->pbufi[ts_conn->cntri], len );
+ ts_conn->sizei = len;
+ ts_conn->pbufi = (uint8 *)os_realloc(ts_conn->pbufi, len + 1); //mem_trim(ts_conn->pbufi, len);
+ if(ts_conn->pbufi == NULL) {
+#if DEBUGSOO > 2
+ ts_printf("memtrim err %p[%d] ", ts_conn->pbufi, len + 1);
+#endif
+ ts_conn->flag.busy_bufi = 0; // обработка bufi окончена
+ return ERR_MEM;
+ }
+ ts_conn->pbufi[len] = '\0'; // вместо os_zalloc;
+ }
+ }
+ ts_conn->cntri = 0;
+ ts_conn->flag.busy_bufi = 0; // обработка bufi окончена
+ return ERR_OK;
+}
+/******************************************************************************
+ * FunctionName : tcpsrv_server_recv
+ * Description : Data has been received on this pcb.
+ * Parameters : arg -- Additional argument to pass to the callback function
+ * pcb -- The connection pcb which received data
+ * p -- The received data (or NULL when the connection has been closed!)
+ * err -- An error code if there has been an error receiving
+ * Returns : ERR_ABRT: if you have called tcp_abort from within the function!
+ ******************************************************************************/
+static err_t TCP_SRV_CODE_ATTR tcpsrv_server_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) {
+ // Sets the callback function that will be called when new data arrives on the connection associated with pcb.
+ // The callback function will be passed a NULL pbuf to indicate that the remote host has closed the connection.
+ TCP_SERV_CONN * ts_conn = arg;
+ if (ts_conn == NULL || pcb == NULL) return ERR_ARG;
+
+// if(syscfg.cfg.b.hi_speed_enable) set_cpu_clk();
+
+ if (p == NULL || err != ERR_OK) { // the remote host has closed the connection.
+ tcpsrv_server_close(ts_conn);
+ return err;
+ };
+ // если нет функции обработки или ожидаем закрытия соединения, то принимаем данные в трубу
+ if ((ts_conn->flag.rx_null != 0) || (ts_conn->pcfg->func_recv == NULL)
+ || (ts_conn->state == SRVCONN_CLOSEWAIT)) { // соединение закрыто? нет.
+ tcp_recved(pcb, p->tot_len + ts_conn->unrecved_bytes); // сообщает стеку, что съели len и можно посылать ACK и принимать новые данные.
+ ts_conn->unrecved_bytes = 0;
+#if DEBUGSOO > 3
+ ts_printf("rec_null %d of %d\n", ts_conn->cntri, p->tot_len);
+#endif
+ pbuf_free(p); // данные выели
+ return ERR_OK;
+ };
+ ts_conn->state = SRVCONN_CONNECT; // был прием
+ ts_conn->recv_check = 0; // счет времени до авто-закрытия с нуля
+ if(p->tot_len) {
+ err = recv_trim_bufi(ts_conn, p->tot_len); // увеличить буфер
+ if(err != ERR_OK) return err;
+ // добавление всего что отдал Lwip в буфер
+ uint32 len = pbuf_copy_partial(p, &ts_conn->pbufi[ts_conn->sizei], p->tot_len, 0);
+ ts_conn->sizei += len;
+ pbuf_free(p); // все данные выели
+ if(!ts_conn->flag.rx_buf) {
+ tcp_recved(pcb, len); // сообщает стеку, что съели len и можно посылать ACK и принимать новые данные.
+ }
+ else ts_conn->unrecved_bytes += len;
+#if DEBUGSOO > 3
+ ts_printf("rec %d of %d :\n", p->tot_len, ts_conn->sizei);
+#endif
+ err = ts_conn->pcfg->func_recv(ts_conn);
+ err_t err2 = recv_trim_bufi(ts_conn, 0); // оптимизировать размер занимаемый буфером
+ if(err2 != ERR_OK) return err2;
+ }
+ return err;
+}
+/******************************************************************************
+ * FunctionName : tcpsrv_unrecved_win
+ * Description : Update the TCP window.
+ * This can be used to throttle data reception (e.g. when received data is
+ * programmed to flash and data is received faster than programmed).
+ * Parameters : TCP_SERV_CONN * ts_conn
+ * Returns : none
+ * После включения throttle, будет принято до 5840 (MAX WIN) + 1460 (MSS) байт?
+ ******************************************************************************/
+void TCP_SRV_CODE_ATTR tcpsrv_unrecved_win(TCP_SERV_CONN *ts_conn) {
+ if (ts_conn->unrecved_bytes) {
+ // update the TCP window
+#if DEBUGSOO > 3
+ ts_printf("recved_bytes=%d\n", ts_conn->unrecved_bytes);
+#endif
+#if 1
+ if(ts_conn->pcb != NULL) tcp_recved(ts_conn->pcb, ts_conn->unrecved_bytes);
+#else
+ struct tcp_pcb *pcb = find_tcp_pcb(ts_conn); // уже закрыто?
+ if(pcb != NULL) tcp_recved(ts_conn->pcb, ts_conn->unrecved_bytes);
+#endif
+ }
+ ts_conn->unrecved_bytes = 0;
+}
+/******************************************************************************
+ * FunctionName : tcpsrv_disconnect
+ * Description : disconnect with host
+ * Parameters : ts_conn
+ * Returns : none
+ ******************************************************************************/
+static void TCP_SRV_CODE_ATTR tcpsrv_disconnect_successful(TCP_SERV_CONN * ts_conn) {
+ ts_conn->pcb = NULL;
+ tcpsrv_list_delete(ts_conn); // remove the node from the server's connection list
+}
+/******************************************************************************
+ * FunctionName : tcpsrv_server_close
+ * Description : The connection shall be actively closed.
+ * Parameters : ts_conn
+ * Returns : none
+ ******************************************************************************/
+static void TCP_SRV_CODE_ATTR tcpsrv_server_close(TCP_SERV_CONN * ts_conn) {
+
+ struct tcp_pcb *pcb = ts_conn->pcb;
+ if(pcb == NULL) {
+#if DEBUGSOO > 3
+ ts_printf("tcpsrv_server_close, state: %s, pcb = NULL!\n", tspsrv_srvconn_state_msg(ts_conn->state));
+#endif
+ return;
+ }
+#if DEBUGSOO > 3
+ ts_printf("tcpsrv_server_close[%d], state: %s\n", pcb->local_port, tspsrv_srvconn_state_msg(ts_conn->state));
+#endif
+ if(ts_conn->state != SRVCONN_CLOSEWAIT && ts_conn->state != SRVCONN_CLOSED) {
+#if DEBUGSOO > 2
+ tcpsrv_print_remote_info(ts_conn);
+ ts_printf("start close...\n");
+#endif
+ ts_conn->state = SRVCONN_CLOSEWAIT;
+ ts_conn->recv_check = 0;
+ ts_conn->flag.wait_sent = 0; // блок передан
+ ts_conn->flag.rx_null = 1; // отключение вызова func_received_data() и прием в null
+ ts_conn->flag.tx_null = 1; // отключение вызова func_sent_callback() и передача в null
+ // отключение функций приема, передачи и poll
+ tcp_recv(pcb, NULL); // отключение приема
+ tcp_sent(pcb, NULL); // отключение передачи
+ tcp_poll(pcb, NULL, 0); // отключение poll
+ tcp_err(pcb, NULL);
+ //
+ if(ts_conn->unrecved_bytes) {
+ tcp_recved(pcb, TCP_WND);
+ ts_conn->unrecved_bytes = 0;
+ }
+ // освободить буфера
+ if (ts_conn->pbufo != NULL) {
+ os_free(ts_conn->pbufo);
+ ts_conn->pbufo = NULL;
+ }
+ ts_conn->sizeo = 0;
+ ts_conn->cntro = 0;
+ if (ts_conn->pbufi != NULL) {
+ os_free(ts_conn->pbufi);
+ ts_conn->pbufi = NULL;
+ }
+ ts_conn->sizei = 0;
+ ts_conn->cntri = 0;
+ }
+ if(ts_conn->state == SRVCONN_CLOSEWAIT || ts_conn->state == SRVCONN_CLOSED) {
+ if (pcb->state == CLOSED || pcb->state == TIME_WAIT) {
+ /*remove the node from the server's active connection list*/
+#if DEBUGSOO > 3
+ ts_printf("close[%d]\n", pcb->local_port);
+#endif
+ tcpsrv_disconnect_successful(ts_conn);
+ } else {
+ if (ts_conn->recv_check > 3) { // счет до принудительного закрытия 3 раза по TCP_SRV_CLOSE_WAIT
+#if DEBUGSOO > 1
+ tcpsrv_print_remote_info(ts_conn);
+ ts_printf("tcp_abandon!\n");
+#endif
+ tcp_poll(pcb, NULL, 0);
+//?/ tcp_err(pcb, NULL);
+ tcp_abandon(pcb, 0);
+// ts_conn->pcb = NULL;
+ // remove the node from the server's active connection list
+ tcpsrv_disconnect_successful(ts_conn);
+ }
+ else if (tcp_close(pcb) != ERR_OK) { // послать закрытие соединения, closing failed
+#if DEBUGSOO > 1
+ tcpsrv_print_remote_info(ts_conn);
+ ts_printf("+ncls+[%d]\n", pcb->local_port);
+#endif
+ // closing failed, try again later
+ tcp_poll(pcb, tcpsrv_poll, 2*(TCP_SRV_CLOSE_WAIT));
+ }
+ else {
+#if DEBUGSOO > 3
+ ts_printf("tcp_close[%d] ok.\n", pcb->local_port);
+#endif
+ tcpsrv_disconnect_successful(ts_conn);
+ }
+ }
+ }
+#if DEBUGSOO > 2
+ else {
+ tcpsrv_print_remote_info(ts_conn);
+ ts_printf("already close!\n");
+ }
+#endif
+}
+/******************************************************************************
+ * FunctionName : tcpsrv_poll (server and client)
+ * Description : The poll function is called every 1 second.
+ * This could be increased, but we don't want to waste resources for bad connections.
+ * Parameters : arg -- Additional argument to pass to the callback function
+ * pcb -- The connection pcb for which data has been acknowledged
+ * Returns : ERR_OK: try to send some data by calling tcp_output
+ * ERR_ABRT: if you have called tcp_abort from within the function!
+ *******************************************************************************/
+static err_t TCP_SRV_CODE_ATTR tcpsrv_poll(void *arg, struct tcp_pcb *pcb) {
+ TCP_SERV_CONN * ts_conn = arg;
+ if (ts_conn == NULL) {
+#if DEBUGSOO > 3
+ ts_printf("poll, ts_conn = NULL! - abandon\n");
+#endif
+ tcp_poll(pcb, NULL, 0);
+ tcp_err(pcb, NULL);
+ tcp_abandon(pcb, 0);
+ return ERR_ABRT;
+ }
+#if DEBUGSOO > 3
+ tcpsrv_print_remote_info(ts_conn);
+ ts_printf("poll: %d %s#%s, %d,%d, pcb:%p\n", ts_conn->recv_check, tspsrv_srvconn_state_msg(ts_conn->state), tspsrv_tcp_state_msg(pcb->state), ts_conn->pcfg->time_wait_rec, ts_conn->pcfg->time_wait_cls), pcb;
+#endif
+ if (ts_conn->pcb != NULL && ts_conn->state != SRVCONN_CLOSEWAIT) {
+ ts_conn->recv_check++;
+ if (pcb->state == ESTABLISHED) {
+ if ((ts_conn->state == SRVCONN_LISTEN
+ && (ts_conn->pcfg->time_wait_rec)
+ && ts_conn->recv_check > ts_conn->pcfg->time_wait_rec)
+ || (ts_conn->state == SRVCONN_CONNECT
+ && (ts_conn->pcfg->time_wait_cls)
+ && ts_conn->recv_check > ts_conn->pcfg->time_wait_cls)) {
+ tcpsrv_server_close(ts_conn);
+ }
+ }
+ else tcpsrv_server_close(ts_conn);
+ }
+ else tcpsrv_server_close(ts_conn);
+#ifdef SRV_WDGREFESH_IN_POOL
+ WDGRefresh();
+#endif
+ return ERR_OK;
+}
+/******************************************************************************
+ * FunctionName : tcpsrv_list_delete
+ * Description : remove the node from the connection list
+ * Parameters : ts_conn
+ * Returns : none
+ *******************************************************************************/
+static void TCP_SRV_CODE_ATTR tcpsrv_list_delete(TCP_SERV_CONN * ts_conn) {
+// if (ts_conn == NULL) return;
+ if(ts_conn->state != SRVCONN_CLOSED) {
+ ts_conn->state = SRVCONN_CLOSED; // исключить повторное вхождение из запросов в func_discon_cb()
+ if (ts_conn->pcfg->func_discon_cb != NULL)
+ ts_conn->pcfg->func_discon_cb(ts_conn);
+ if(phcfg == NULL || ts_conn->pcfg == NULL) return; // если в func_discon_cb() было вызвано tcpsrv_close_all() и т.д.
+ }
+#if DEBUGSOO > 3
+ ts_printf("tcpsrv_list_delete (%p)\n", ts_conn->pcb);
+#endif
+ TCP_SERV_CONN ** p = &ts_conn->pcfg->conn_links;
+ TCP_SERV_CONN *tcpsrv_cmp = ts_conn->pcfg->conn_links;
+ while (tcpsrv_cmp != NULL) {
+ if (tcpsrv_cmp == ts_conn) {
+ *p = ts_conn->next;
+ ts_conn->next = NULL;
+ ts_conn->pcfg->conn_count--;
+ if (ts_conn->linkd != NULL) {
+ os_free(ts_conn->linkd);
+ ts_conn->linkd = NULL;
+ }
+ if (ts_conn->pbufo != NULL) {
+ os_free(ts_conn->pbufo);
+ ts_conn->pbufo = NULL;
+ }
+ if (ts_conn->pbufi != NULL) {
+ os_free(ts_conn->pbufi);
+ ts_conn->pbufi = NULL;
+ }
+ os_free(ts_conn);
+ return; // break;
+ }
+ p = &tcpsrv_cmp->next;
+ tcpsrv_cmp = tcpsrv_cmp->next;
+ };
+}
+//-----------------------------------------------------------------------------
+static void tspsrv_delete_pcb(TCP_SERV_CONN * ts_conn)
+{
+ struct tcp_pcb *pcb = find_tcp_pcb(ts_conn);
+ if(pcb) {
+ tcp_arg(pcb, NULL);
+ tcp_recv(pcb, NULL);
+ tcp_err(pcb, NULL);
+ tcp_poll(pcb, NULL, 0);
+ tcp_sent(pcb, NULL);
+ tcp_recved(pcb, TCP_WND);
+ tcp_close(pcb);
+ ts_conn->pcb = NULL;
+ }
+ tcpsrv_list_delete(ts_conn);
+}
+/******************************************************************************
+ * FunctionName : tcpsrv_error (server and client)
+ * Description : The pcb had an error and is already deallocated.
+ * The argument might still be valid (if != NULL).
+ * Parameters : arg -- Additional argument to pass to the callback function
+ * err -- Error code to indicate why the pcb has been closed
+ * Returns : none
+ *******************************************************************************/
+static void TCP_SRV_CODE_ATTR tcpsrv_error(void *arg, err_t err) {
+ TCP_SERV_CONN * ts_conn = arg;
+// struct tcp_pcb *pcb = NULL;
+ if (ts_conn != NULL) {
+#if DEBUGSOO > 2
+ tcpsrv_print_remote_info(ts_conn);
+ ts_printf("error %d (%s)\n", err, tspsrv_error_msg(err));
+#elif DEBUGSOO > 1
+ tcpsrv_print_remote_info(ts_conn);
+#ifdef LWIP_DEBUG
+ ts_printf("error %d (%s)\n", err, tspsrv_error_msg(err));
+#else
+ ts_printf("error %d\n", err);
+#endif
+#endif
+ if (ts_conn->state != SRVCONN_CLOSEWAIT) {
+ if(ts_conn->pcb != NULL) {
+// && ts_conn->state != SRVCONN_CLOSED) {
+// && (ts_conn->state != SRVCONN_CONNECT || ts_conn->state == SRVCONN_LISTEN)) {
+#if DEBUGSOO > 1
+ ts_printf("eclose[%d]\n", ts_conn->pcfg->port);
+#endif
+ tcpsrv_list_delete(ts_conn); // remove the node from the server's connection list
+ };
+ };
+ }
+}
+/******************************************************************************
+ * FunctionName : tcpsrv_tcp_accept
+ * Description : A new incoming connection has been accepted.
+ * Parameters : arg -- Additional argument to pass to the callback function
+ * pcb -- The connection pcb which is accepted
+ * err -- An unused error code, always ERR_OK currently
+ * Returns : acception result
+ *******************************************************************************/
+static err_t TCP_SRV_CODE_ATTR tcpsrv_server_accept(void *arg, struct tcp_pcb *pcb, err_t err) {
+ struct tcp_pcb_listen *lpcb = (struct tcp_pcb_listen*) arg;
+ TCP_SERV_CFG *p = tcpsrv_server_port2pcfg(pcb->local_port);
+ TCP_SERV_CONN * ts_conn;
+ if (p == NULL) return ERR_ARG;
+ if (system_get_free_heap_size() < p->min_heap) {
+#if DEBUGSOO > 1
+ ts_printf("srv[%u] new listen - low heap size!\n", p->port);
+#endif
+ return ERR_MEM;
+ }
+ if (p->conn_count >= p->max_conn) {
+ if(p->flag.srv_reopen) {
+#if DEBUGSOO > 1
+ ts_printf("srv[%u] reconnect!\n", p->port);
+#endif
+ if (p->conn_links != NULL) {
+ tspsrv_delete_pcb(p->conn_links);
+ };
+ }
+ else {
+#if DEBUGSOO > 1
+ ts_printf("srv[%u] new listen - max connection!\n", p->port);
+#endif
+ return ERR_CONN;
+ }
+ }
+ ts_conn = (TCP_SERV_CONN *) os_zalloc(sizeof(TCP_SERV_CONN));
+ if (ts_conn == NULL) {
+#if DEBUGSOO > 1
+ ts_printf("srv[%u] new listen - out of mem!\n", ts_conn->pcfg->port);
+#endif
+ return ERR_MEM;
+ }
+ ts_conn->pcfg = p;
+ // перенести флаги по умолчанию на данное соединение
+ ts_conn->flag = p->flag;
+ tcp_accepted(lpcb); // Decrease the listen backlog counter
+ // tcp_setprio(pcb, TCP_PRIO_MIN); // Set priority ?
+ // init/copy data ts_conn
+ ts_conn->pcb = pcb;
+ ts_conn->remote_port = pcb->remote_port;
+ ts_conn->remote_ip.dw = pcb->remote_ip.addr;
+// *(uint16 *) &ts_conn->flag = 0; //zalloc
+// ts_conn->recv_check = 0; //zalloc
+// ts_conn->linkd = NULL; //zalloc
+ // Insert new ts_conn
+ ts_conn->next = ts_conn->pcfg->conn_links;
+ ts_conn->pcfg->conn_links = ts_conn;
+ ts_conn->pcfg->conn_count++;
+ ts_conn->state = SRVCONN_LISTEN;
+ // Tell TCP that this is the structure we wish to be passed for our callbacks.
+ tcp_arg(pcb, ts_conn);
+ // Set up the various callback functions
+ tcp_err(pcb, tcpsrv_error);
+ tcp_sent(pcb, tcpsrv_server_sent);
+ tcp_recv(pcb, tcpsrv_server_recv);
+ tcp_poll(pcb, tcpsrv_poll, 2); /* every 1/2 seconds */
+#if MEMP_MEM_MALLOC // tcp_alloc() уже управляет убийством TIME_WAIT если MEMP_MEM_MALLOC == 0
+ if(ts_conn->flag.pcb_time_wait_free) tcpsrv_check_max_tm_tcp_pcb();
+ // http://www.serverframework.com/asynchronousevents/2011/01/time-wait-and-its-design-implications-for-protocols-and-scalable-servers.html
+#endif
+ if (p->func_listen != NULL)
+ return p->func_listen(ts_conn);
+ return ERR_OK;
+}
+/******************************************************************************
+ * FunctionName : tcpsrv_server_port2pcfg
+ * Description : поиск конфига servera по порту
+ * Parameters : номер порта
+ * Returns : указатель на TCP_SERV_CFG или NULL
+ *******************************************************************************/
+TCP_SERV_CFG * TCP_SRV_CODE_ATTR tcpsrv_server_port2pcfg(uint16 portn) {
+ TCP_SERV_CFG * p;
+ for (p = phcfg; p != NULL; p = p->next)
+ if (p->port == portn) return p;
+ return NULL;
+}
+/******************************************************************************
+ tcpsrv_init server.
+ *******************************************************************************/
+TCP_SERV_CFG * TCP_SRV_CODE_ATTR tcpsrv_init(uint16 portn) {
+ // if (portn == 0) portn = 80;
+ if (portn == 0) return NULL;
+ TCP_SERV_CFG * p;
+ for (p = phcfg; p != NULL; p = p->next) {
+ if (p->port == portn) {
+#if DEBUGSOO > 0
+ ts_printf(txt_tcpsrv_already_initialized);
+#endif
+ return NULL;
+ }
+ }
+ p = (TCP_SERV_CFG *) os_zalloc(sizeof(TCP_SERV_CFG));
+ if (p == NULL) {
+#if DEBUGSOO > 0
+ ts_printf(txt_tcpsrv_out_of_mem);
+#endif
+ return NULL;
+ }
+ p->port = portn;
+ p->conn_count = 0;
+ p->min_heap = TCP_SRV_MIN_HEAP_SIZE;
+ p->time_wait_rec = TCP_SRV_RECV_WAIT;
+ p->time_wait_cls = TCP_SRV_END_WAIT;
+ // p->phcfg->conn_links = NULL; // zalloc
+ // p->pcb = NULL; // zalloc
+ // p->lnk = NULL; // zalloc
+ p->max_conn = TCP_SRV_MAX_CONNECTIONS;
+ p->func_listen = tcpsrv_listen_default;
+ p->func_discon_cb = tcpsrv_disconnect_calback_default;
+ p->func_sent_cb = tcpsrv_sent_callback_default;
+ p->func_recv = tcpsrv_received_data_default;
+ return p;
+}
+/******************************************************************************
+ tcpsrv_start
+ *******************************************************************************/
+err_t TCP_SRV_CODE_ATTR tcpsrv_start(TCP_SERV_CFG *p) {
+ err_t err = ERR_OK;
+ if (p == NULL) {
+#if DEBUGSOO > 0
+ ts_printf(txt_tcpsrv_NULL_pointer);
+#endif
+ return ERR_ARG;
+ }
+ if (p->pcb != NULL) {
+#if DEBUGSOO > 0
+ ts_printf(txt_tcpsrv_already_initialized);
+#endif
+ return ERR_USE;
+ }
+ p->pcb = tcp_new();
+
+ if (p->pcb != NULL) {
+ tcp_setprio(p->pcb, TCP_SRV_PRIO);
+ err = tcp_bind(p->pcb, IP_ADDR_ANY, p->port); // Binds pcb to a local IP address and port number.
+ if (err == ERR_OK) { // If another connection is bound to the same port, the function will return ERR_USE, otherwise ERR_OK is returned.
+ p->pcb = tcp_listen(p->pcb); // Commands pcb to start listening for incoming connections.
+ // When an incoming connection is accepted, the function specified with the tcp_accept() function
+ // will be called. pcb must have been bound to a local port with the tcp_bind() function.
+ // The tcp_listen() function returns a new connection identifier, and the one passed as an
+ // argument to the function will be deallocated. The reason for this behavior is that less
+ // memory is needed for a connection that is listening, so tcp_listen() will reclaim the memory
+ // needed for the original connection and allocate a new smaller memory block for the listening connection.
+ // tcp_listen() may return NULL if no memory was available for the listening connection.
+ // If so, the memory associated with pcb will not be deallocated.
+ if (p->pcb != NULL) {
+ tcp_arg(p->pcb, p->pcb);
+ // insert new tcpsrv_config
+ p->next = phcfg;
+ phcfg = p;
+ // initialize callback arg and accept callback
+ tcp_accept(p->pcb, tcpsrv_server_accept);
+ return err;
+ }
+ }
+ tcp_abandon(p->pcb, 0);
+ p->pcb = NULL;
+ } else
+ err = ERR_MEM;
+#if DEBUGSOO > 0
+ ts_printf("tcpsrv: not new tcp!\n");
+#endif
+ return err;
+}
+/******************************************************************************
+ tcpsrv_close
+ *******************************************************************************/
+err_t TCP_SRV_CODE_ATTR tcpsrv_close(TCP_SERV_CFG *p) {
+ if (p == NULL) {
+#if DEBUGSOO > 0
+ ts_printf(txt_tcpsrv_NULL_pointer);
+#endif
+ return ERR_ARG;
+ };
+ TCP_SERV_CFG **pwr = &phcfg;
+ TCP_SERV_CFG *pcmp = phcfg;
+ while (pcmp != NULL) {
+ if (pcmp == p) {
+ *pwr = p->next;
+ while (p->conn_links != NULL) {
+ tspsrv_delete_pcb(p->conn_links);
+ };
+ if(p->pcb != NULL) tcp_close(p->pcb);
+ os_free(p);
+ p = NULL;
+ return ERR_OK; // break;
+ }
+ pwr = &pcmp->next;
+ pcmp = pcmp->next;
+ };
+#if DEBUGSOO > 2
+ ts_printf("tcpsrv: srv_cfg not find!\n");
+#endif
+ return ERR_CONN;
+}
+/******************************************************************************
+ tcpsrv_close_port
+ *******************************************************************************/
+err_t TCP_SRV_CODE_ATTR tcpsrv_close_port(uint16 portn)
+{
+ if(portn) return tcpsrv_close(tcpsrv_server_port2pcfg(portn));
+ else return ERR_ARG;
+}
+/******************************************************************************
+ tcpsrv_close_all_tcp_pcb
+ *******************************************************************************/
+int TCP_SRV_CODE_ATTR tcpsrv_close_all_tcp_pcb(void)
+{
+ struct tcp_pcb *pcb;
+ int ret = 0;
+ for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
+#if DEBUGSOO > 3
+ ts_printf("tcpsrv: abort %p pcb\n", pcb);
+#endif
+ tcp_abort(pcb);
+ ret = 1;
+ }
+ return ret;
+}
+/******************************************************************************
+ tcpsrv_delete_all_tm_tcp_pcb
+ *******************************************************************************/
+void TCP_SRV_CODE_ATTR tcpsrv_delete_all_tm_tcp_pcb(void)
+{
+ struct tcp_pcb *pcb;
+ for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
+#if DEBUGSOO > 3
+ ts_printf("tcpsrv: del tm %p pcb\n", pcb);
+#endif
+ tcp_pcb_remove(&tcp_tw_pcbs, pcb);
+ memp_free(MEMP_TCP_PCB, pcb);
+ }
+}
+/******************************************************************************
+ tcpsrv_close_all
+ *******************************************************************************/
+err_t TCP_SRV_CODE_ATTR tcpsrv_close_all(void)
+{
+ err_t err = ERR_OK;
+ while(phcfg != NULL && err == ERR_OK) err = tcpsrv_close(phcfg);
+ if(tcpsrv_close_all_tcp_pcb()) vTaskDelay(50);
+ tcpsrv_delete_all_tm_tcp_pcb();
+ return err;
+}
+
diff --git a/RTLGDB/Project/tcpsrv/tcp_srv_conn.h b/RTLGDB/Project/tcpsrv/tcp_srv_conn.h
new file mode 100644
index 0000000..9fa14f2
--- /dev/null
+++ b/RTLGDB/Project/tcpsrv/tcp_srv_conn.h
@@ -0,0 +1,188 @@
+#ifndef __TCP_SERV_CONN_H__
+/***********************************
+ * FileName: tcp_srv_conn.h
+ * Tcp сервачек для ESP8266
+ * PV` ver1.0 20/12/2014
+ * PV` ver1.0 29/10/2016 для RTL87xx
+ ***********************************/
+#define __TCP_SERV_CONN_H__
+
+#include "user_config.h"
+#include "tcp.h"
+
+#include "lwip/err.h"
+
+#undef mMIN
+#define mMIN(a, b) ((a < b)? a : b)
+#define mMAX(a, b) ((a>b)?a:b)
+
+
+enum srvconn_state {
+ SRVCONN_NONE =0,
+ SRVCONN_CLOSEWAIT, // ожидает закрытия
+ SRVCONN_LISTEN, // соединение открыто, ждет rx или tx
+ SRVCONN_CONNECT, // соединение открыто, было rx или tx
+ SRVCONN_CLOSED // соединение закрыто
+};
+
+// приоритет pcb 1..127 1 - min, 127 - max
+#ifndef TCP_SRV_PRIO
+#define TCP_SRV_PRIO 99 // TCP_PRIO_MIN
+#endif
+
+// максимальное кол-во TCP c TIME_WAIT
+#ifndef MAX_TIME_WAIT_PCB
+#define MAX_TIME_WAIT_PCB 10
+#endif
+
+// кол-во одновременно открытых соединений по умолчанию
+#ifndef TCP_SRV_MAX_CONNECTIONS
+ #define TCP_SRV_MAX_CONNECTIONS mMIN(MEMP_NUM_TCP_PCB, 10)
+#endif
+
+// порт сервера по умолчанию
+#ifndef TCP_SRV_SERVER_PORT
+ #define TCP_SRV_SERVER_PORT 80
+#endif
+
+
+#define SRV_WDGREFESH_IN_POOL // использовать WDGRefresh() в tcpsrv_poll()
+
+// время (сек), по умолчанию, ожидания запроса (передачи пакета) от клиента, до авто-закрытия соединения,
+// при = 0 заменяется на эти 5 сек.
+#ifndef TCP_SRV_RECV_WAIT
+ #define TCP_SRV_RECV_WAIT 5
+#endif
+// время (сек), по умолчанию, до авто-закрытия соединения после приема или передачи,
+// при = 0 заменяется на эти 5 сек.
+#ifndef TCP_SRV_END_WAIT
+ #define TCP_SRV_END_WAIT 5
+#endif
+
+// время (в сек) до повтора закрытия соединения (исполняется до 3-х раз).
+#define TCP_SRV_CLOSE_WAIT 5 // 5 сек
+
+// минимальный размер heap по умолчанию, при открытии нового соединения, при = 0 заменяется на это:
+#define TCP_SRV_MIN_HEAP_SIZE 32768 // самый минимум от 6Kb
+
+// максимальный размер выделяемого буфера в heap для приема порции
+#ifndef TCP_SRV_SERVER_MAX_RXBUF
+#define TCP_SRV_SERVER_MAX_RXBUF TCP_WND // (TCP_MSS*3) // 1460*2=2920, 1460*3=4380, 1460*4=5840
+#endif
+
+// размер выделяемого буфера в heap для передачи при буферизированном выводе
+#ifndef TCP_SRV_SERVER_DEF_TXBUF
+#define TCP_SRV_SERVER_DEF_TXBUF TCP_SND_BUF //(TCP_MSS*3) // 1460*2=2920, 1460*3=4380, 1460*4=5840
+#endif
+
+#define ID_CLIENTS_PORT 3 // РґРѕ 3-С… clients
+#define tcpsrv_init_client1() tcpsrv_init(1) // tcp2uart_client
+#define tcpsrv_init_client2() tcpsrv_init(2) // mdb_tcp_client
+#define tcpsrv_init_client3() tcpsrv_init(3)
+
+#define TCP_CLIENT_NEXT_CONNECT_S 5 // syscfg.tcp_client_twait // 5000 // через 5 сек
+#define TCP_CLIENT_MAX_CONNECT_RETRY 7 // до 7 раз с интервалом TCP_CLIENT_NEXT_CONNECT_MS
+
+//--------------------------------------------------------------------------
+// Структура соединения
+//
+typedef struct t_tcpsrv_conn_flags {
+ uint16 srv_reopen: 1; //0001 открытие нового соединения более max_conn ведет к закрытию наиболее старого соединения.
+ uint16 pcb_time_wait_free: 1; //0002 проверка на макс кол-во и уничтожение pcb с TIME_WAIT при вызове disconnect() (иначе pcb TIME_WAIT 60 сек http://www.serverframework.com/asynchronousevents/2011/01/time-wait-and-its-design-implications-for-protocols-and-scalable-servers.html)
+ uint16 nagle_disabled: 1; //0004 выключение nagle
+ uint16 rx_buf: 1; //0008 прием в буфер, используется ручное управление размером окна TCP
+ uint16 rx_null: 1; //0010 отключение вызова func_received_data() и прием в null (устанавливается автоматически при вызове tcpsrv_disconnect())
+ uint16 tx_null: 1; //0020 отключение вызова func_sent_callback() и передача в null (устанавливается автоматически при вызове tcpsrv_disconnect())
+ uint16 wait_sent: 1; //0040 ожидет завершения/подтверждения передачи от lwip
+ uint16 busy_bufo: 1; //0080 идет обработка bufo
+ uint16 busy_bufi: 1; //0100 идет обработка bufi
+ uint16 tmp0: 1; //0200 резерв
+ uint16 tmp1: 1; //0400 резерв
+ // далее идут биты не относящиеся к работе tcp_srv_conn
+ uint16 user_flg1: 1; //0800 для нужд процедур уровнем выше (пока свободен)
+ uint16 user_flg2: 1; //1000 для нужд процедур уровнем выше (пока свободен)
+ uint16 user_option1: 1; //2000 для нужд процедур обработки переменных (использован для hexdump, xml_mdb в web_int_callbacks.c)
+ uint16 user_option2: 1; //4000 для нужд процедур обработки переменных (использован для xml_mdb в web_int_callbacks.c)
+} __attribute__((packed)) tcpsrv_conn_flags;
+
+typedef struct t_TCP_SERV_CONN {
+ volatile tcpsrv_conn_flags flag;//+0 флаги соеднения
+ enum srvconn_state state; //+4 состояние
+ struct t_TCP_SERV_CFG *pcfg; //+8 указатель на базовую структуру сервера
+ uint16 recv_check; //+12 счет тиков соединения в tcpsrv_poll
+ uint16 remote_port; //+16 номер порта клиента
+ union { //+20 ip клиента
+ uint32 dw;
+ uint8 b[4];
+ } remote_ip;
+ struct t_TCP_SERV_CONN *next; //+24 указатель на следующую структуру
+ struct tcp_pcb *pcb; //+28 указатель на pcb в Lwip
+ uint8 *pbufo; //+32 указатель на сегмент с передаваемыми данными
+ uint8 *ptrtx; //+36 указатель на ещё не переданные данные
+ uint8 *pbufi; //+40 указатель на сегмент буфера с принимаемыми данными
+ uint16 sizeo; //+44 размер буфера передачи
+ uint16 sizei; //+48 размер приемного буфера (кол-во принятых и ещё не обработанных байт)
+ uint16 cntro; //+52 кол-во обработанных байт в буфере передачи
+ uint16 cntri; //+56 кол-во обработанных байт в буфере приема
+ uint16 unrecved_bytes; //+60 используется при ручном управлении TCP WIN / This can be used to throttle data reception
+ // далее идут переменные не относящиеся к работе tcp_srv_conn
+ uint8 *linkd; //+64 указатель на прилепленные данные пользователя (при закрытии соединения вызывается os_close(linkd), если linkd != NULL;
+} TCP_SERV_CONN;
+
+
+//--------------------------------------------------------------------------
+// Вызываемые функции пользователя (calback-и)
+//
+typedef void (*func_disconect_calback)(TCP_SERV_CONN *ts_conn); // соединение закрыто
+typedef err_t (*func_listen)(TCP_SERV_CONN *ts_conn); // новый клиент
+typedef err_t (*func_received_data)(TCP_SERV_CONN *ts_conn); // принято всего ts_conn->sizei байт, лежат в буфере по ts_conn->pbufi, по выходу принимается обработанных ts_conn->cntri;
+typedef err_t (*func_sent_callback)(TCP_SERV_CONN *ts_conn); // блок данных передан
+
+//--------------------------------------------------------------------------
+// Структура конфигурации tcp сервера
+//
+typedef struct t_TCP_SERV_CFG {
+ struct t_tcpsrv_conn_flags flag; // начальные флаги для соединения
+ uint16 port; // номер порта
+ uint16 min_heap; // минимальный размер heap при открытии нового соединения, при = 0 заменяется на 8192.
+ uint8 max_conn; // максимальное кол-во одновременных соединений
+ uint8 conn_count; // кол-во текущих соединений, при инициализации прописывает 0
+ uint8 time_wait_rec; // время (сек) ожидания запроса (передачи пакета) от клиента, до авто-закрытия соединения, по умолчанию TCP_SRV_RECV_WAIT сек.
+ uint8 time_wait_cls; // время (сек) до авто-закрытия соединения после приема или передачи, по умолчанию TCP_SRV_END_WAIT сек.
+ TCP_SERV_CONN * conn_links; // указатель на цепочку активных соединений, при инициализации или отсуствии активных соединений = NULL
+ struct tcp_pcb *pcb; // начальный pcb [LISTEN] если сервер, иначе NULL
+ func_disconect_calback func_discon_cb; // функция вызываемая после закрытия соединения, если = NULL - не вызывается
+ func_listen func_listen; // функция вызываемая при присоединении клиента или коннекта к серверу, если = NULL - не вызывается
+ func_sent_callback func_sent_cb; // функция вызываемая после передачи данных или наличию места в ip стеке для следушей передачи данных, если = NULL - не вызывается (+см. флаги)
+ func_received_data func_recv; // функция вызываемая при приеме данных, если = NULL - не вызывается (+см. флаги)
+ struct t_TCP_SERV_CFG *next; // следующий экземпляр структуры сервера/клиента
+}TCP_SERV_CFG;
+//--------------------------------------------------------------------------
+// Данные
+//
+extern TCP_SERV_CFG *phcfg; // указатель на цепочку TCP_SERV_CFG (стартовавших серверов)
+//--------------------------------------------------------------------------
+// Функции
+//
+err_t tcpsrv_int_sent_data(TCP_SERV_CONN * ts_conn, uint8 *psent, uint16 length); // передать length байт (внутрення функция - никаких проверок)
+void tcpsrv_disconnect(TCP_SERV_CONN * ts_conn); // закрыть соединение
+void tcpsrv_print_remote_info(TCP_SERV_CONN *ts_conn); // выводит remote_ip:remote_port [conn_count] os_printf("srv x.x.x.x:x [n] ")
+TCP_SERV_CFG * tcpsrv_server_port2pcfg(uint16 portn); // поиск структуры конфига по номеру порта
+void tcpsrv_unrecved_win(TCP_SERV_CONN *ts_conn); // Восстановить размер TCP WIN, если используется ручное управление размером окна TCP
+
+void tcpsrv_disconnect_calback_default(TCP_SERV_CONN *ts_conn);
+err_t tcpsrv_listen_default(TCP_SERV_CONN *ts_conn);
+err_t tcpsrv_sent_callback_default(TCP_SERV_CONN *ts_conn);
+err_t tcpsrv_received_data_default(TCP_SERV_CONN *ts_conn);
+
+TCP_SERV_CFG *tcpsrv_init(uint16 portn);
+err_t tcpsrv_start(TCP_SERV_CFG *p);
+err_t tcpsrv_close(TCP_SERV_CFG *p);
+err_t tcpsrv_close_port(uint16 portn);
+err_t tcpsrv_close_all(void);
+
+const char * tspsrv_error_msg(err_t err);
+const char * tspsrv_tcp_state_msg(enum tcp_state state);
+const char * tspsrv_srvconn_state_msg(enum srvconn_state state);
+
+#endif // __TCP_SERV_CONN_H__
diff --git a/RTLGDB/Project/user_config.h b/RTLGDB/Project/user_config.h
new file mode 100644
index 0000000..0c3dca4
--- /dev/null
+++ b/RTLGDB/Project/user_config.h
@@ -0,0 +1,26 @@
+#ifndef _user_config_h_
+#define _user_config_h_
+
+#define SYS_VERSION "1.0.1"
+#include "sdk_ver.h"
+
+#define USE_WEB 80 // включить в трансялцию порт Web, если =0 - по умолчанию выключен
+#define WEBSOCKET_ENA 1 // включить WEBSOCKET
+#define USE_SNTP 1 // включить в трансялцию драйвер SNTP, если =0 - по умолчанию выключен, = 1 - по умолчанию включен.
+#define USE_NETBIOS 1 // включить в трансялцию драйвер NETBIOS, если =0 - по умолчанию выключен.
+
+#define WEB_DEBUG_FUNCTIONS 1 // =1 - включить в WEB отладочные функции, =0 отключить (остается только конфигурация WiFi)
+
+// #define WEB_INA219_DRV 1 (set in project.mk !)
+// #define WEB_ADC_DRV 1 (set in project.mk !)
+
+
+#ifdef _MSC_VER // IntelliSense
+#define __attribute__(packed)
+//typedef int8_t err_t;
+#endif
+
+
+#endif // _user_config_h_
+
+
diff --git a/RTLGDB/Project/user_start.c b/RTLGDB/Project/user_start.c
new file mode 100644
index 0000000..9255dc7
--- /dev/null
+++ b/RTLGDB/Project/user_start.c
@@ -0,0 +1,202 @@
+/*
+ * user_start.c
+ *
+ * Created on: 26/03/2017
+ * Author: pvvx
+ */
+#include "user_config.h"
+#include "platform_autoconf.h"
+#include "autoconf.h"
+#include "FreeRTOS.h"
+#include "freertos_pmu.h"
+#include "task.h"
+#include "diag.h"
+#include "netbios/netbios.h"
+#include "sntp/sntp.h"
+#include "sys_cfg.h"
+#include "wifi_api.h"
+#include "web/web_srv.h"
+#include "webfs/webfs.h"
+
+#include "MPU6050.h"
+//#include "SSD1306.h"
+//#include "WS2812.h"
+#include "wifi_api.h"
+
+#include "gpio_api.h" // mbed
+#include "i2c_api.h"
+#include "pinmap.h"
+
+#include "lwip/pbuf.h"
+#include "lwip/udp.h"
+#include "lwip/tcp.h"
+
+#include "flashconf_tst.h"
+#include "efuse_tst.h"
+
+#define OFFSET 0x298
+#define GAIN_DIV 0x34C
+#define AD2MV(ad,offset,gain) (((ad/16)-offset)*1000/gain)
+
+
+
+struct SystemCfg syscfg = {
+ .cfg.w = SYS_CFG_DEBUG_ENA
+ | SYS_CFG_PIN_CLR_ENA
+#if defined(USE_NETBIOS) && USE_NETBIOS
+ | SYS_CFG_NETBIOS_ENA
+#endif
+#if defined(USE_SNTP) && USE_SNTP
+ | SYS_CFG_SNTP_ENA
+#endif
+ ,
+#if defined(USE_WEB)
+ .web_port = USE_WEB,
+#else
+ .web_port = 0,
+#endif
+ .web_twrec = 5,
+ .web_twcls = 5
+};
+
+void connect_start(void)
+{
+ info_printf("\%s: Time at start %d ms.\n", __func__, xTaskGetTickCount());
+}
+
+void connect_close(void)
+{
+ info_printf("\%s: Time at start %d ms.\n", __func__, xTaskGetTickCount());
+}
+
+void user_start(void)
+{
+ info_printf("\%s: Time at start %d ms.\n", __func__, xTaskGetTickCount());
+
+}
+
+void sys_write_cfg(void)
+{
+ flash_write_cfg(&syscfg, FEEP_ID_SYS_CFG, sizeof(syscfg));
+}
+
+extern void console_init(void);
+
+void udp_echoserver_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, struct ip_addr *addr, uint16_t port);
+void user_init2_thrd(void)
+{
+ gpio_t gpio_usrled, gpio_usrbt, gpio_pwren, gpio_pwrbt;
+ MPU6050_DataPack dp[MPU6050_PACKSIZE];
+ struct pbuf *pb;
+ struct udp_pcb *upcb;
+ ip_addr_t servIP;
+
+ for (uint16_t i = 0; i < MPU6050_PACKSIZE; i++)
+ {
+ dp[i].X = 0;
+ //dp[i].Y = 0;
+ //dp[i].Z = 0;
+ }
+
+ //IP4_ADDR(&servIP, 192, 168, 1, 39);
+ //IP4_ADDR(&servIP, 192, 168, 137, 1);
+ IP4_ADDR(&servIP, 192, 168, 1, 55);
+
+ gpio_usrled.direction = PIN_OUTPUT;
+ gpio_usrled.mode = PullNone;
+ gpio_init(&gpio_usrled, PC_2);
+
+ gpio_pwren.direction = PIN_OUTPUT;
+ gpio_pwren.mode = PullNone;
+ gpio_init(&gpio_pwren, PC_0);
+
+ gpio_pwrbt.direction = PIN_INPUT;
+ gpio_pwrbt.mode = PullDown;
+ gpio_init(&gpio_pwrbt, PC_1);
+
+ gpio_usrbt.direction = PIN_INPUT;
+ gpio_usrbt.mode = PullUp;
+ gpio_init(&gpio_usrbt, PC_3);
+
+ gpio_write(&gpio_pwren, 1);
+ gpio_write(&gpio_usrled, 1);
+
+ vTaskDelay(1000);
+
+ MPU6050_Init();
+
+ upcb = udp_new();
+
+ for (;;)
+ {
+ vTaskDelay(50);
+ WDGRefresh();
+
+ if (gpio_read(&gpio_pwrbt))
+ {
+ gpio_write(&gpio_usrled, 0);
+ gpio_write(&gpio_pwren, 0);
+ }
+
+ if (wifi_st_status == WIFI_STA_CONNECTED)
+ {
+ if(MPU6050_IsDataPacketReady(&dp))
+ {
+ if (upcb)
+ {
+ //DBG_8195A("Send UDP data...\n");
+ udp_connect(upcb, &servIP, 5001);
+
+ pb = pbuf_alloc(PBUF_TRANSPORT, sizeof(MPU6050_DataPack) * MPU6050_PACKSIZE, PBUF_RAM);
+ memcpy(pb->payload, &dp, sizeof(MPU6050_DataPack) * MPU6050_PACKSIZE);
+
+ udp_send(upcb, pb);
+ udp_disconnect(upcb);
+ pbuf_free(pb);
+ }
+ }
+ }
+ }
+ vTaskDelete(NULL);
+}
+
+void user_init_thrd(void)
+{
+ //if(syscfg.cfg.b.pin_clear_cfg_enable && 0)
+ //{
+ // user_test_clear_pin();
+ wifi_cfg.load_flg = 0;
+ //}
+ //else flash_read_cfg(&syscfg, FEEP_ID_SYS_CFG, sizeof(syscfg));
+
+ if(!syscfg.cfg.b.debug_print_enable) print_off = 1;
+
+ /* Initilaize the console stack */
+ console_init();
+
+ /* Web Disk Init */
+ WEBFSInit();
+
+ /* Load cfg, init WiFi + LwIP init, WiFi start if wifi_cfg.mode != RTW_MODE_NONE */
+ wifi_init();
+
+#if defined(USE_NETBIOS)
+ if(syscfg.cfg.b.netbios_ena) netbios_init();
+#endif
+#if defined(USE_SNTP)
+ if(syscfg.cfg.b.sntp_ena) sntp_init();
+#endif
+ // webstuff_init(); // httpd_init();
+ webserver_init(syscfg.web_port);
+
+ if(syscfg.cfg.b.powersave_enable)
+ {
+ release_wakelock(~WAKELOCK_WLAN);
+ }
+
+ // xTaskCreate(x_init_thrd, "wifi_init", 1024, NULL, tskIDLE_PRIORITY + 1 + PRIORITIE_OFFSET, NULL);
+
+ /* Kill init thread after all init tasks done */
+ vTaskDelete(NULL);
+}
+
diff --git a/RTLGDB/Project/web/web_auth.c b/RTLGDB/Project/web/web_auth.c
new file mode 100644
index 0000000..4237284
--- /dev/null
+++ b/RTLGDB/Project/web/web_auth.c
@@ -0,0 +1,52 @@
+/*
+ * web_auth.c
+ *
+ * Created on: 23/04/2017.
+ * Author: pvvx
+ */
+#include "autoconf.h"
+#include "FreeRTOS.h"
+#include "diag.h"
+#include "web_utils.h"
+#include "wifi_api.h"
+#include "web_srv.h"
+#include "rtl8195a/rtl_libc.h"
+#include "esp_comp.h"
+
+
+/* ----------------------------------------------------------------------------------
+ * pbuf[77] = Username and password are combined into a string "username:password"
+ * Return: Authorization Level
+ * 0 - Not Authorized */
+
+uint8 UserAuthorization(uint8 *pbuf, size_t declen)
+{
+ uint8 * psw = rtl_strchr(pbuf, ':');
+ if(psw != NULL)
+ {
+#if USE_WEB_AUTH_LEVEL
+ if(rtl_strcmp(pbuf, "rtl871x:webfs_write") == 0)
+ {
+ return WEB_AUTH_LEVEL_WEBFS;
+ }
+ if(rtl_strcmp(pbuf, "rtl871x:ota_write") == 0)
+ {
+ return WEB_AUTH_LEVEL_OTA;
+ }
+ if(rtl_strcmp(pbuf, "rtl871x:supervisor") == 0)
+ {
+ return WEB_AUTH_LEVEL_SUPERVISOR;
+ }
+#endif
+ *psw++ = 0;
+ if(rom_xstrcmp(wifi_ap_cfg.ssid, pbuf) && rom_xstrcmp( wifi_ap_cfg.password, psw))
+ {
+ return WEB_AUTH_LEVEL_USER;
+ }
+ if(rom_xstrcmp(wifi_st_cfg.ssid, pbuf) && rom_xstrcmp( wifi_st_cfg.password, psw))
+ {
+ return WEB_AUTH_LEVEL_USER1;
+ }
+ }
+ return 0;
+}
diff --git a/RTLGDB/Project/web/web_int_callbacks.c b/RTLGDB/Project/web/web_int_callbacks.c
new file mode 100644
index 0000000..8de1378
--- /dev/null
+++ b/RTLGDB/Project/web/web_int_callbacks.c
@@ -0,0 +1,700 @@
+/******************************************************************************
+ * FileName: web_int_callbacks.c
+ * Description: The web server inernal callbacks.
+*******************************************************************************/
+
+#include "user_config.h"
+#ifdef USE_WEB
+#include "autoconf.h"
+#include "FreeRTOS.h"
+#include "task.h"
+#include "diag.h"
+#include "tcm_heap.h"
+#include "lwip/tcp.h"
+#include "flash_eep.h"
+#include "device_lock.h"
+#include "ethernetif.h"
+#include "tcpsrv/tcp_srv_conn.h"
+#include "web_srv_int.h"
+#include "web_utils.h"
+#include "webfs/webfs.h"
+#include "rtl8195a/rtl_libc.h"
+#include "sys_cfg.h"
+#include "wifi_api.h"
+#include "sys_api.h"
+#include "esp_comp.h"
+#include "sdk_ver.h"
+
+#ifdef USE_NETBIOS
+#include "netbios/netbios.h"
+#endif
+
+#ifdef USE_SNTP
+#include "sntp/sntp.h"
+#endif
+
+#ifdef USE_CAPTDNS
+#include "captdns.h"
+#endif
+
+#ifdef USE_MODBUS
+#include "modbustcp.h"
+#include "mdbtab.h"
+#endif
+
+#ifdef USE_RS485DRV
+#include "driver/rs485drv.h"
+#endif
+
+#ifdef USE_OVERLAY
+#include "overlay.h"
+#endif
+
+#undef atoi
+#define atoi rom_atoi
+
+//#define mMIN(a, b) ((alinkd;
+ unsigned int len = web_conn->msgbufsize - web_conn->msgbuflen;
+ if(len > WAV_HEADER_SIZE + 10) {
+ len -= WAV_HEADER_SIZE;
+ WAV_HEADER * ptr = (WAV_HEADER *) &web_conn->msgbuf[web_conn->msgbuflen];
+ os_memcpy(ptr, &wav_header, WAV_HEADER_SIZE);
+ ptr->dsize = len;
+ web_conn->msgbuflen += WAV_HEADER_SIZE;
+ len >>= 1;
+ read_adcs((uint16 *)(web_conn->msgbuf + web_conn->msgbuflen), len, 0x0808);
+ web_conn->msgbuflen += len << 1;
+ }
+ if(!CheckSCB(SCB_WEBSOC)) SetSCB(SCB_FCLOSE | SCB_DISCONNECT); // connection close
+}
+#endif // TEST_SEND_WAVE
+
+//===============================================================================
+// WiFi Scan XML
+//-------------------------------------------------------------------------------
+extern void wifi_set_timer_scan(int ms);
+static void ICACHE_FLASH_ATTR web_wscan_xml(TCP_SERV_CONN *ts_conn)
+{
+ WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *) ts_conn->linkd;
+ web_scan_handler_t * pwscn_rec = &web_scan_handler_ptr;
+ // Check if this is a first round call
+ if(CheckSCB(SCB_RETRYCB)==0) {
+ int i = 0;
+ web_conn->udata_start = 0;
+ if(pwscn_rec->flg == 2) {
+ i = pwscn_rec->ap_count;
+ wifi_set_timer_scan(7000);
+ } else if(pwscn_rec->flg == 0) api_wifi_scan(NULL);
+ tcp_puts_fd("%d", i);
+ if(i == 0) return;
+ }
+ while(web_conn->msgbuflen + 96 + 10 + 32 <= web_conn->msgbufsize) {
+ if(pwscn_rec->flg && web_conn->udata_start < pwscn_rec->ap_count) {
+ rtw_scan_result_t *si = &pwscn_rec->ap_details[web_conn->udata_start];
+ uint8 ssid[32*6 + 1];
+ int len = si->SSID.len;
+ if(len > 32) len = 32;
+ si->SSID.val[len] = '\0';
+ if(web_conn->msgbuflen + 96 + 10 + htmlcode(ssid, si->SSID.val, 32*6, 32) > web_conn->msgbufsize) break;
+ tcp_puts_fd("%d%d" MACSTR "%s%d%d%d",
+ web_conn->udata_start,
+ si->channel,
+ rtw_security_to_idx(si->security),
+ MAC2STR(si->BSSID.octet),
+ ssid,
+ si->signal_strength,
+// si->band, // rtw_802_11_band_t
+ si->bss_type & 3, // rtw_bss_type_t
+ si->wps_type); // rtw_wps_type_t
+ web_conn->udata_start++;
+ if(web_conn->udata_start >= pwscn_rec->ap_count) {
+ wifi_close_scan();
+ ClrSCB(SCB_RETRYCB);
+ return;
+ }
+ }
+ else {
+ wifi_close_scan();
+ ClrSCB(SCB_RETRYCB);
+ return;
+ }
+ }
+ // repeat in the next call ...
+ SetSCB(SCB_RETRYCB);
+ SetNextFunSCB(web_wscan_xml);
+ return;
+}
+#ifdef USE_MODBUS
+//===============================================================================
+// Mdb XML
+//-------------------------------------------------------------------------------
+void ICACHE_FLASH_ATTR web_modbus_xml(TCP_SERV_CONN *ts_conn)
+{
+ WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *) ts_conn->linkd;
+ while(web_conn->msgbuflen + 24 <= web_conn->msgbufsize) {
+ if(web_conn->udata_start < web_conn->udata_stop) {
+ uint16 val16;
+ if(RdMdbData((uint8 *)&val16, web_conn->udata_start, 1) != 0) tcp_puts_fd("?", web_conn->udata_start, web_conn->udata_start);
+ else {
+ if(ts_conn->flag.user_option2) {
+ if(ts_conn->flag.user_option1) {
+ tcp_puts_fd("0x%04x", web_conn->udata_start, val16, web_conn->udata_start);
+ }
+ else {
+ tcp_puts_fd("%04x", web_conn->udata_start, val16, web_conn->udata_start);
+ };
+ }
+ else {
+ if(ts_conn->flag.user_option1) {
+ tcp_puts_fd("%d", web_conn->udata_start, (sint32)((sint16)val16), web_conn->udata_start);
+ }
+ else {
+ tcp_puts_fd("%u", web_conn->udata_start, val16, web_conn->udata_start);
+ };
+ };
+ };
+ web_conn->udata_start++;
+ }
+ else {
+ ClrSCB(SCB_RETRYCB);
+ return;
+ }
+ }
+ // repeat in the next call ...
+ SetSCB(SCB_RETRYCB);
+ SetNextFunSCB(web_modbus_xml);
+ return;
+}
+#endif
+//===============================================================================
+// RAM hexdump
+//-------------------------------------------------------------------------------
+void ICACHE_FLASH_ATTR web_hexdump(TCP_SERV_CONN *ts_conn)
+{
+ WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *) ts_conn->linkd;
+ union {
+ uint32 dw[4];
+ uint8 b[16];
+ }data;
+ web_conn->udata_start &= 0xfffffff0;
+ uint32 *addr = (uint32 *)web_conn->udata_start;
+ int i;
+ web_conn->udata_stop &= 0xfffffff0;
+ while(web_conn->msgbuflen + (9+3*16+17+2) <= web_conn->msgbufsize) {
+// if((uint32)addr < 0x9A000000) {
+ if((uint32)addr >= 0x98000000 && (uint32)addr < 0x9A000000) {
+ OpenFlash();
+ }
+ tcp_puts("%08x", addr);
+ for(i=0 ; i < 4 ; i++) data.dw[i] = *addr++;
+ web_conn->udata_start = (uint32)addr;
+ if(ts_conn->flag.user_option1) { // dword or byte ?
+ for(i=0 ; i < 4 ; i++) tcp_puts(" %08x", data.dw[i]);
+ }
+ else {
+ for(i=0 ; i < 16 ; i++) tcp_puts(" %02x", data.b[i]);
+ }
+ if((uint32)addr >= 0x98000000 && (uint32)addr < 0x9A000000) {
+ CloseFlash();
+ }
+ tcp_put(' '); tcp_put(' ');
+ for(i=0 ; i < 16 ; i++) tcp_put((data.b[i] >=' ' && data.b[i] != 0x7F)? data.b[i] : '.');
+ tcp_puts("\r\n");
+ if((uint32)addr >= web_conn->udata_stop) {
+ ClrSCB(SCB_RETRYCB);
+ if(!CheckSCB(SCB_WEBSOC)) SetSCB(SCB_FCLOSE | SCB_DISCONNECT); // connection close
+ return;
+ }
+// } else {
+// tcp_puts("%p = Bad address!\r\n", addr);
+// ClrSCB(SCB_RETRYCB);
+// if(!CheckSCB(SCB_WEBSOC)) SetSCB(SCB_FCLOSE | SCB_DISCONNECT); // connection close
+// return;
+// };
+ }
+ // repeat in the next call ...
+ SetSCB(SCB_RETRYCB);
+ SetNextFunSCB(web_hexdump);
+ return;
+}
+/******************************************************************************
+ * FunctionName : web saved flash
+ * Description : Processing the flash data send
+ * Parameters : none (Calback)
+ * Returns : none
+*******************************************************************************/
+void ICACHE_FLASH_ATTR web_get_flash(TCP_SERV_CONN *ts_conn)
+{
+ WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
+ // Check if this is a first round call
+ if(CheckSCB(SCB_RETRYCB)==0) {
+ if(web_conn->udata_start == web_conn->udata_stop) return;
+#if DEBUGSOO > 2
+ os_printf("file_size:%08x ", web_conn->udata_stop - web_conn->udata_start );
+#endif
+ }
+ // Get/put as many bytes as possible
+ unsigned int len = mMIN(web_conn->msgbufsize - web_conn->msgbuflen, web_conn->udata_stop - web_conn->udata_start);
+ // Read Flash addr = web_conn->webfinc_offsets, len = x, buf = sendbuf
+#if DEBUGSOO > 2
+ os_printf("%08x..%08x ",web_conn->udata_start, web_conn->udata_start + len );
+#endif
+ device_mutex_lock(RT_DEV_LOCK_FLASH);
+ if(spi_flash_read(web_conn->udata_start, web_conn->msgbuf, len)) {
+ web_conn->udata_start += len;
+ web_conn->msgbuflen += len;
+ if(web_conn->udata_start < web_conn->udata_stop) {
+ SetNextFunSCB(web_get_flash);
+ device_mutex_unlock(RT_DEV_LOCK_FLASH);
+ SetSCB(SCB_RETRYCB);
+ return;
+ };
+ };
+ device_mutex_unlock(RT_DEV_LOCK_FLASH);
+ ClrSCB(SCB_RETRYCB);
+// SetSCB(SCB_FCLOSE | SCB_DISCONNECT);
+ return;
+}
+/******************************************************************************
+ * FunctionName : web saved flash
+ * Description : Processing the flash data send
+ * Parameters : none (Calback)
+ * Returns : none
+*******************************************************************************/
+void ICACHE_FLASH_ATTR web_get_ram(TCP_SERV_CONN *ts_conn)
+{
+ WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
+ // Check if this is a first round call
+ if(CheckSCB(SCB_RETRYCB)==0) { // On initial call, проверка параметров
+ if(web_conn->udata_start == web_conn->udata_stop) {
+// SetSCB(SCB_FCLOSE | SCB_DISCONNECT);
+ return;
+ }
+#if DEBUGSOO > 2
+ os_printf("file_size:%08x ", web_conn->udata_stop - web_conn->udata_start );
+#endif
+ }
+ // Get/put as many bytes as possible
+ uint32 len = mMIN(web_conn->msgbufsize - web_conn->msgbuflen, web_conn->udata_stop - web_conn->udata_start);
+ if((uint32)web_conn->udata_start >= 0x98000000 && (uint32)web_conn->udata_start < 0x9A000000) {
+ OpenFlash();
+ }
+ copy_align4(web_conn->msgbuf, (void *)(web_conn->udata_start), len);
+ if((uint32)web_conn->udata_start >= 0x98000000 && (uint32)web_conn->udata_start < 0x9A000000) {
+ CloseFlash();
+ }
+ web_conn->msgbuflen += len;
+ web_conn->udata_start += len;
+#if DEBUGSOO > 2
+ os_printf("%08x-%08x ",web_conn->udata_start, web_conn->udata_start + len );
+#endif
+ if(web_conn->udata_start != web_conn->udata_stop) {
+ SetSCB(SCB_RETRYCB);
+ SetNextFunSCB(web_get_ram);
+ return;
+ };
+ ClrSCB(SCB_RETRYCB);
+// SetSCB(SCB_FCLOSE | SCB_DISCONNECT);
+ return;
+}
+/******************************************************************************
+ * FunctionName : web_callback
+ * Description : callback
+ * Parameters : struct TCP_SERV_CONN
+ * Returns : none
+ ******************************************************************************/
+void ICACHE_FLASH_ATTR web_int_callback(TCP_SERV_CONN *ts_conn, uint8 *cstr)
+{
+ WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
+// uint8 *cstr = &web_conn->msgbuf[web_conn->msgbuflen];
+ {
+ uint8 *vstr = os_strchr(cstr, '=');
+ if(vstr != NULL) {
+ *vstr++ = '\0';
+ web_int_vars(ts_conn, cstr, vstr);
+ return;
+ }
+ }
+#if DEBUGSOO > 3
+ os_printf("[%s]\n", cstr);
+#endif
+ ifcmp("start") tcp_puts("0x%08x", web_conn->udata_start);
+ else ifcmp("stop") tcp_puts("0x%08x", web_conn->udata_stop);
+#if USE_WEB_AUTH_LEVEL
+ else ifcmp("realm") tcp_puts("%u", web_conn->auth_realm);
+ else ifcmp("auth") tcp_puts("%u", web_conn->auth_level);
+#endif
+ else ifcmp("xml_") {
+ cstr+=4;
+ ifcmp("scan") web_wscan_xml(ts_conn);
+#if WEB_DEBUG_FUNCTIONS
+ else
+ {
+#if USE_WEB_AUTH_LEVEL
+ if(web_conn->auth_level < WEB_AUTH_LEVEL_USER)
+ return;
+ else
+#endif
+ {
+ web_conn->udata_start&=~3;
+ ifcmp("ram") tcp_puts("0x%08x", *((uint32*)web_conn->udata_start));
+ else tcp_put('?');
+ web_conn->udata_start += 4;
+ }
+ }
+#endif
+ }
+ else ifcmp("sys_") {
+ cstr+=4;
+ ifcmp("url") tcp_strcpy(get_new_hostname());
+ else ifcmp("cid") tcp_puts("%08x", HalGetChipId());
+ else ifcmp("fid") tcp_puts("%08x", spi_flash_get_id());
+ else ifcmp("fsize") tcp_puts("%u", spi_flash_real_size()); // flashchip->chip_size
+ else ifcmp("sdkver") tcp_strcpy_fd(SDK_VERSION);
+ else ifcmp("sysver") tcp_strcpy_fd(SYS_VERSION);
+ else ifcmp("webver") tcp_strcpy_fd(WEB_SVERSION);
+ else ifcmp("heap") tcp_puts("%u", xPortGetFreeHeapSize());
+ else ifcmp("heapm") tcp_puts("%u", xPortGetMinimumEverFreeHeapSize());
+ else ifcmp("tcmh") tcp_puts("%u", tcm_heap_freeSpace());
+ else ifcmp("time") tcp_puts("%u", xTaskGetTickCount());
+ else ifcmp("mactime") {
+ if(wifi_mode) {
+ union {
+ uint32 dw[2];
+ uint64 dd;
+ }ux;
+ ux.dd = *((uint64_t *)(WIFI_REG_BASE + 0x0560)); // REG_TSFTR -> #include "hal_com_reg.h"
+ tcp_puts("0x%08x%08x", ux.dw[1], ux.dw[0]);
+ }
+ }
+ else ifcmp("clkcpu") tcp_puts("%u", HalGetCpuClk());
+ else ifcmp("debug") tcp_put('1' - (print_off & 1)); // rtl_print on/off
+#if WEB_DEBUG_FUNCTIONS
+ else ifcmp("restart") {
+#if USE_WEB_AUTH_LEVEL
+ if(web_conn->auth_level < WEB_AUTH_LEVEL_USER) return;
+#endif
+ webserver_qfn((web_ex_func_cb)sys_reset, NULL, 200);
+ }
+ else ifcmp("ram") tcp_puts("0x%08x", *((uint32 *)(ahextoul(cstr+3)&(~3))));
+ else ifcmp("rdec") tcp_puts("%d", *((uint32 *)(ahextoul(cstr+4)&(~3))));
+#endif // #if WEB_DEBUG_FUNCTIONS
+ else ifcmp("ip") {
+ uint32 cur_ip;
+ if(netif_default != NULL) cur_ip = netif_default->ip_addr.addr;
+ tcp_puts(IPSTR, IP2STR(&cur_ip));
+ }
+#ifdef USE_NETBIOS
+ else ifcmp("netbios") {
+ if(syscfg.cfg.b.netbios_ena) tcp_strcpy(netbios_name);
+ }
+#endif
+ else tcp_put('?');
+ }
+#ifdef WEB_INA219_DRV
+ else ifcmp("ina219") {
+ if(CheckSCB(SCB_WEBSOC)) {
+extern int ina219_ws(TCP_SERV_CONN *ts_conn, char cmd);
+ int x = ina219_ws(ts_conn, cstr[6]);
+ if(x < 0) SetSCB(SCB_FCLOSE|SCB_DISCONNECT);
+ else tcp_puts("%d", x);
+ }
+ }
+#endif
+#ifdef WEB_MLX90614_DRV
+ else ifcmp("mlx90614") {
+ if(CheckSCB(SCB_WEBSOC)) {
+extern int mlx90614_ws(TCP_SERV_CONN *ts_conn, char cmd);
+ int x = mlx90614_ws(ts_conn, cstr[6]);
+ if(x < 0) SetSCB(SCB_FCLOSE|SCB_DISCONNECT);
+ else tcp_puts("%d", x);
+ }
+ }
+#endif
+#ifdef WEB_ADC_DRV
+ else ifcmp("adc")
+ {
+ if(CheckSCB(SCB_WEBSOC))
+ {
+ extern int adc_ws(TCP_SERV_CONN *ts_conn, char cmd);
+ int x = adc_ws(ts_conn, cstr[6]);
+ if(x < 0) SetSCB(SCB_FCLOSE|SCB_DISCONNECT);
+ else tcp_puts("%d", x);
+ }
+ }
+#endif
+#ifdef WEB_MPU6050
+ else ifcmp("mpu6050")
+ {
+ if (CheckSCB(SCB_WEBSOC))
+ {
+
+ }
+ }
+#endif
+ else ifcmp("cfg_") {
+ cstr += 4;
+ ifcmp("web_") {
+ cstr += 4;
+ ifcmp("port") tcp_puts("%u", syscfg.web_port);
+ else ifcmp("twrec") tcp_puts("%u", syscfg.web_twrec);
+ else ifcmp("twcls") tcp_puts("%u", syscfg.web_twcls);
+ else ifcmp("twd") tcp_put((syscfg.cfg.b.web_time_wait_delete)? '1' : '0');
+ else tcp_put('?');
+ }
+ else ifcmp("sleep") tcp_put((syscfg.cfg.b.powersave_enable)? '1' : '0');
+ else ifcmp("pinclr") tcp_put((syscfg.cfg.b.pin_clear_cfg_enable)? '1' : '0');
+ else ifcmp("debug") tcp_put((syscfg.cfg.b.debug_print_enable)? '1' : '0');
+#ifdef USE_NETBIOS
+ else ifcmp("netbios") tcp_put((syscfg.cfg.b.netbios_ena)? '1' : '0');
+#endif
+#ifdef USE_SNTP
+ else ifcmp("sntp") tcp_put((syscfg.cfg.b.sntp_ena)? '1' : '0');
+#endif
+#ifdef USE_CAPTDNS
+ else ifcmp("cdns") tcp_put((syscfg.cfg.b.cdns_ena)? '1' : '0');
+#endif
+ else tcp_put('?');
+ }
+ else ifcmp("wifi_") {
+ cstr+=5;
+ ifcmp("rdcfg") read_wifi_cfg(-1);
+ else ifcmp("newcfg") webserver_qfn((web_ex_func_cb)wifi_run, (void *)((uint32)wifi_cfg.mode), 200);
+ else ifcmp("cmode") tcp_puts("%d", wifi_mode);
+ else ifcmp("mode") tcp_puts("%d", wifi_cfg.mode);
+ else ifcmp("bgn") tcp_puts("%d", wifi_cfg.bgn);
+ else ifcmp("txpow") tcp_puts("%u", wifi_cfg.tx_pwr);
+ else ifcmp("lflg") tcp_puts("%u", wifi_cfg.load_flg);
+ else ifcmp("sflg") tcp_puts("%u", wifi_cfg.save_flg);
+ else ifcmp("adpt") tcp_puts("%u", wifi_cfg.adaptivity);
+ else ifcmp("country") tcp_puts("%u", wifi_cfg.country_code);
+ else ifcmp("ap_") {
+ cstr+=3;
+ ifcmp("ssid") {
+ wifi_ap_cfg.ssid[NDIS_802_11_LENGTH_SSID] = '\0';
+ tcp_strcpy(wifi_ap_cfg.ssid);
+ }
+ else ifcmp("psw") {
+ wifi_ap_cfg.password[IW_PASSPHRASE_MAX_SIZE] = '\0';
+ tcp_strcpy(wifi_ap_cfg.password);
+ }
+ else ifcmp("chl") tcp_puts("%u", wifi_ap_cfg.channel);
+ else ifcmp("mcns") tcp_puts("%u", wifi_ap_cfg.max_sta);
+ else ifcmp("auth") tcp_put((wifi_ap_cfg.security) ? '1' : '0');
+ else ifcmp("hssid") tcp_put((wifi_ap_cfg.ssid_hidden & 1) + '0');
+ else ifcmp("bint") tcp_puts("%u", wifi_ap_cfg.beacon_interval);
+ else ifcmp("mac") tcp_puts(MACSTR, MAC2STR(xnetif[WLAN_AP_NETIF_NUM].hwaddr));
+ else ifcmp("hostname") tcp_strcpy(lwip_host_name[1]);
+ else ifcmp("dhcp") tcp_puts("%u", wifi_ap_dhcp.mode);
+ else ifcmp("ip") tcp_puts(IPSTR, IP2STR(&wifi_ap_dhcp.ip));
+ else ifcmp("gw") tcp_puts(IPSTR, IP2STR(&wifi_ap_dhcp.gw));
+ else ifcmp("msk") tcp_puts(IPSTR, IP2STR(&wifi_ap_dhcp.mask));
+ else ifcmp("cip") tcp_puts(IPSTR, IP2STR(&xnetif[WLAN_ST_NETIF_NUM].ip_addr.addr));
+ // else ifcmp("mac") strtomac(pvar, wifi_ap_cfg.macaddr);
+ // else ifcmp("sip") tcp_puts(IPSTR, IP2STR(&wifi_ap_dhcp.start_ip));
+ // else ifcmp("eip") tcp_puts(IPSTR, IP2STR(&wifi_ap_dhcp.end_ip));
+ #if DEBUGSOO > 2
+ else os_printf(" - none! ");
+ #endif
+ }
+ else ifcmp("st_") {
+ cstr+=3;
+ ifcmp("rssi") {
+ int rssi;
+ wifi_get_rssi(&rssi);
+ tcp_puts("%d", rssi);
+ }
+ else ifcmp("status") tcp_puts("%u", wifi_st_status);
+ else ifcmp("arec") tcp_puts("%u", wifi_st_cfg.autoreconnect);
+ else ifcmp("rect") tcp_puts("%u", wifi_st_cfg.reconnect_pause);
+ ifcmp("ssid") {
+ wifi_st_cfg.ssid[NDIS_802_11_LENGTH_SSID] = '\0';
+ tcp_strcpy(wifi_st_cfg.ssid);
+ }
+ else ifcmp("psw") {
+ wifi_st_cfg.password[IW_PASSPHRASE_MAX_SIZE] = '\0';
+ tcp_strcpy(wifi_st_cfg.password);
+ }
+ else ifcmp("mac") tcp_puts(MACSTR, MAC2STR(xnetif[WLAN_ST_NETIF_NUM].hwaddr));
+ else ifcmp("bssid") tcp_puts(MACSTR, MAC2STR(wifi_st_cfg.bssid));
+ else ifcmp("sbss") tcp_puts("%u", wifi_st_cfg.flg);
+ else ifcmp("sleep") tcp_puts("%d", wifi_st_cfg.sleep);
+ else ifcmp("dtim") tcp_puts("%u", wifi_st_cfg.dtim);
+#if LWIP_NETIF_HOSTNAME
+ else ifcmp("hostname") tcp_strcpy(lwip_host_name[0]);
+#endif
+ else ifcmp("auth") tcp_puts("%u", wifi_st_cfg.security);
+ else ifcmp("dhcp") tcp_puts("%u", wifi_st_dhcp.mode);
+ else ifcmp("ip") tcp_puts(IPSTR, IP2STR(&wifi_st_dhcp.ip));
+ else ifcmp("gw") tcp_puts(IPSTR, IP2STR(&wifi_st_dhcp.gw));
+ else ifcmp("msk") tcp_puts(IPSTR, IP2STR(&wifi_st_dhcp.mask));
+ #if DEBUGSOO > 5
+ else os_printf(" - none!\n");
+ #endif
+ }
+#if DEBUGSOO > 5
+ else os_printf(" - none!\n");
+#endif
+ }
+ else ifcmp("bin_") {
+#if USE_WEB_AUTH_LEVEL
+ if(web_conn->auth_level < WEB_AUTH_LEVEL_USER) return;
+#endif
+ cstr+=4;
+ ifcmp("flash") {
+ cstr+=5;
+ if(*cstr == '_') {
+ cstr++;
+#if WEB_DEBUG_FUNCTIONS
+ ifcmp("all") {
+ web_conn->udata_start = 0;
+ web_conn->udata_stop = spi_flash_real_size();
+ web_get_flash(ts_conn);
+ }
+ else ifcmp("sec_") {
+ web_conn->udata_start = ahextoul(cstr+4) << 12;
+ web_conn->udata_stop = web_conn->udata_start + FLASH_SECTOR_SIZE;
+ web_get_flash(ts_conn);
+ }
+ else
+#endif // #if WEB_DEBUG_FUNCTIONS
+ ifcmp("disk") {
+ web_conn->udata_start = WEBFS_base_addr();
+ web_conn->udata_stop = web_conn->udata_start + WEBFS_curent_size();
+ web_get_flash(ts_conn);
+ }
+ else tcp_put('?');
+ }
+ else web_get_flash(ts_conn);
+ }
+#if WEB_DEBUG_FUNCTIONS
+ else ifcmp("ram") web_get_ram(ts_conn);
+#endif // #if WEB_DEBUG_FUNCTIONS
+ else tcp_put('?');
+ }
+#if WEB_DEBUG_FUNCTIONS
+ else ifcmp("hexdmp") {
+#if USE_WEB_AUTH_LEVEL
+ if(web_conn->auth_level < WEB_AUTH_LEVEL_USER) return;
+#endif
+ if(cstr[6]=='d') ts_conn->flag.user_option1 = 1;
+ else ts_conn->flag.user_option1 = 0;
+ web_hexdump(ts_conn);
+ }
+#endif // #if WEB_DEBUG_FUNCTIONS
+ else ifcmp("web_") {
+ cstr+=4;
+ ifcmp("port") tcp_puts("%u", ts_conn->pcfg->port);
+ else ifcmp("host") tcp_puts(IPSTR ":%d", IP2STR(&(ts_conn->pcb->local_ip.addr)), ts_conn->pcb->local_port);
+ else ifcmp("remote") tcp_puts(IPSTR ":%d", IP2STR(&(ts_conn->remote_ip.dw)), ts_conn->remote_port);
+ else ifcmp("twrec") tcp_puts("%u", ts_conn->pcfg->time_wait_rec);
+ else ifcmp("twcls") tcp_puts("%u", ts_conn->pcfg->time_wait_cls);
+ else tcp_put('?');
+ }
+ else ifcmp("wfs_") {
+ cstr+=4;
+ ifcmp("files") tcp_puts("%u", numFiles);
+ else ifcmp("addr") tcp_puts("0x%08x", WEBFS_base_addr());
+ else ifcmp("size") tcp_puts("%u", WEBFS_curent_size());
+ else ifcmp("max_size") tcp_puts("%u", WEBFS_max_size());
+ else tcp_put('?');
+ }
+#ifdef USE_OVERLAY
+ else ifcmp("ovl") {
+ cstr += 3;
+ if(*cstr == ':') {
+ int i = ovl_loader(cstr + 1);
+ if (i == 0) {
+ if(CheckSCB(SCB_WEBSOC)) {
+ tcp_puts("%d", ovl_call(1));
+ }
+ else {
+ web_conn->web_disc_cb = (web_func_disc_cb)ovl_call; // адрес старта оверлея
+ web_conn->web_disc_par = 1; // параметр функции - инициализация
+ }
+ }
+ tcp_puts("%d", i);
+ }
+ else if(*cstr == '$') {
+ if(ovl_call != NULL) tcp_puts("%d", ovl_call(ahextoul(cstr + 1)));
+ else tcp_put('?');
+ }
+ else if(*cstr == '@') {
+ if(ovl_call != NULL) tcp_puts("%d", ovl_call((int) cstr + 1));
+ else tcp_put('?');
+ }
+ else tcp_put('?');
+ }
+#endif
+#ifdef USE_SNTP
+ else ifcmp("sntp_") {
+ cstr += 5;
+ ifcmp("time") tcp_puts("%u", sntp_gen_system_time(0)); // get_sntp_time
+ else tcp_put('?');
+ }
+#endif
+#ifdef TEST_SEND_WAVE
+ else ifcmp("test_adc") web_test_adc(ts_conn);
+#endif
+ else ifcmp("hellomsg") tcp_puts_fd("Web on RTL871x!");
+ else tcp_put('?');
+}
+
+#endif // USE_WEB
diff --git a/RTLGDB/Project/web/web_int_vars.c b/RTLGDB/Project/web/web_int_vars.c
new file mode 100644
index 0000000..61b2779
--- /dev/null
+++ b/RTLGDB/Project/web/web_int_vars.c
@@ -0,0 +1,396 @@
+/******************************************************************************
+ * FileName: webserver.c
+ * Description: The web server mode configuration.
+*******************************************************************************/
+
+#include "user_config.h"
+#ifdef USE_WEB
+#include "autoconf.h"
+#include "FreeRTOS.h"
+#include "freertos_pmu.h"
+#include "task.h"
+#include "diag.h"
+#include "lwip/ip.h"
+#include "lwip/ip_addr.h"
+#include "lwip/tcp.h"
+#include "tcpsrv/tcp_srv_conn.h"
+#include "ethernetif.h"
+#include "web_srv_int.h"
+#include "web_utils.h"
+#include "webfs/webfs.h"
+#include "flash_eep.h"
+#include "device_lock.h"
+#include "rtl8195a/rtl_libc.h"
+#include "sys_cfg.h"
+#include "wifi_api.h"
+#include "sys_api.h"
+#include "esp_comp.h"
+
+#ifdef USE_NETBIOS
+#include "netbios/netbios.h"
+#endif
+
+#ifdef USE_SNTP
+#include "sntp/sntp.h"
+#endif
+
+#ifdef USE_LWIP_PING
+#include "lwip/app/ping.h"
+struct ping_option pingopt; // for test
+#endif
+
+#ifdef USE_CAPTDNS
+#include "captdns.h"
+#endif
+
+#ifdef USE_MODBUS
+#include "modbustcp.h"
+#include "mdbtab.h"
+#endif
+
+#ifdef USE_RS485DRV
+#include "driver/rs485drv.h"
+#include "mdbrs485.h"
+#endif
+
+#ifdef USE_OVERLAY
+#include "overlay.h"
+#endif
+
+extern void web_get_ram(TCP_SERV_CONN *ts_conn);
+extern void web_get_flash(TCP_SERV_CONN *ts_conn);
+extern void web_hexdump(TCP_SERV_CONN *ts_conn);
+
+#define ifcmp(a) if(rom_xstrcmp(cstr, a))
+
+extern int rom_atoi(const char *);
+#undef atoi
+#define atoi rom_atoi
+
+typedef uint32 (* call_func)(uint32 a, uint32 b, uint32 c);
+extern QueueHandle_t xQueueWebSrv;
+
+/******************************************************************************
+ * FunctionName : parse_url
+ * Description : parse the received data from the server
+ * Parameters : CurHTTP -- the result of parsing the url
+ * Returns : none
+*******************************************************************************/
+void ICACHE_FLASH_ATTR web_int_vars(TCP_SERV_CONN *ts_conn, uint8 *pcmd, uint8 *pvar)
+{
+ WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
+ uint32 val = ahextoul(pvar);
+ char *cstr = pcmd;
+#if DEBUGSOO > 1
+ os_printf("[%s=%s]\n", pcmd, pvar);
+#endif
+ ifcmp("start") web_conn->udata_start = val;
+ else ifcmp("stop") web_conn->udata_stop = val;
+#if USE_WEB_AUTH_LEVEL
+ else ifcmp("user") web_conn->auth_level = UserAuthorization(pvar, strlen(pvar));
+ else if(web_conn->auth_level < WEB_AUTH_LEVEL_USER) {
+ if(!web_conn->auth_realm) web_conn->auth_realm = WEB_AUTH_LEVEL_USER;
+ SetSCB(SCB_AUTH);
+ return;
+ }
+#endif
+#if WEB_DEBUG_FUNCTIONS
+ else ifcmp("sys_") {
+ cstr+=4;
+ ifcmp("restart") {
+ if(val == 12345) webserver_qfn((web_ex_func_cb)sys_reset, NULL, 200);
+ }
+ else ifcmp("ram") { uint32 *ptr = (uint32 *)(ahextoul(cstr+3)&(~3)); str_array(pvar, ptr, 32); }
+ else ifcmp("debug") print_off = (!val) & 1; // rtl_print on/off
+ else ifcmp("dsleep") deepsleep_ex(DSLEEP_WAKEUP_BY_TIMER, val);
+#ifdef USE_LWIP_PING
+ else ifcmp("ping") {
+// struct ping_option *pingopt = (struct ping_option *)UartDev.rcv_buff.pRcvMsgBuff;
+ pingopt.ip = ipaddr_addr(pvar);
+ pingopt.count = 3;
+ pingopt.recv_function=NULL;
+ pingopt.sent_function=NULL;
+ ping_start(&pingopt);
+ }
+#endif
+ }
+#endif // #if WEB_DEBUG_FUNCTIONS
+ else ifcmp("cfg_") {
+ cstr += 4;
+ ifcmp("web_") {
+ cstr += 4;
+ ifcmp("port") {
+ if(syscfg.web_port != val) {
+ webserver_qfn((web_ex_func_cb)webserver_reinit, (void *)((uint32)syscfg.web_port), 200);
+ syscfg.web_port = val;
+ }
+ }
+ else ifcmp("twd") {
+ if(val) {
+ syscfg.cfg.b.web_time_wait_delete = 1;
+ ts_conn->pcfg->flag.pcb_time_wait_free = 1;
+ }
+ else {
+ syscfg.cfg.b.web_time_wait_delete = 0;
+ ts_conn->pcfg->flag.pcb_time_wait_free = 0;
+ }
+ }
+ else ifcmp("twrec") {
+ syscfg.web_twrec = val;
+ ts_conn->pcfg->time_wait_rec = val;
+ }
+ else ifcmp("twcls") {
+ syscfg.web_twcls = val;
+ ts_conn->pcfg->time_wait_cls = val;
+ }
+#if DEBUGSOO > 5
+ else os_printf(" - none!\n");
+#endif
+ }
+ else ifcmp("pinclr") syscfg.cfg.b.pin_clear_cfg_enable = (val)? 1 : 0;
+ else ifcmp("sleep") {
+ syscfg.cfg.b.powersave_enable = (val)? 1 : 0;
+ if(val) release_wakelock(~WAKELOCK_WLAN);
+ else acquire_wakelock(~WAKELOCK_WLAN);
+ }
+ else ifcmp("debug") {
+ syscfg.cfg.b.debug_print_enable = val;
+ print_off = (!val) & 1; // rtl_print on/off
+ }
+ else ifcmp("save") {
+ if(val == 2) SetSCB(SCB_SYSSAVE); // по закрытию соединения вызвать sys_write_cfg()
+ else if(val == 1) sys_write_cfg();
+ }
+#ifdef USE_NETBIOS
+ else ifcmp("netbios") {
+ syscfg.cfg.b.netbios_ena = (val)? 1 : 0;
+ if(syscfg.cfg.b.netbios_ena) netbios_init();
+ else netbios_off();
+ }
+#endif
+#ifdef USE_SNTP
+ else ifcmp("sntp") {
+ syscfg.cfg.b.sntp_ena = (val)? 1 : 0;
+ if(syscfg.cfg.b.sntp_ena) sntp_init();
+ else sntp_stop();
+ }
+#endif
+#ifdef USE_CAPTDNS
+ else ifcmp("cdns") {
+ syscfg.cfg.b.cdns_ena = (val)? 1 : 0;
+ if(syscfg.cfg.b.cdns_ena && wifi_softap_get_station_num()) captdns_init();
+ else captdns_close();
+ }
+#endif
+#if DEBUGSOO > 5
+ else os_printf(" - none!\n");
+#endif
+ // sys_write_cfg();
+ }
+ else ifcmp("wifi_") {
+ cstr+=5;
+ ifcmp("scan") api_wifi_scan(NULL);
+ else ifcmp("rdcfg") web_conn->udata_stop = read_wifi_cfg(val);
+ else ifcmp("newcfg") webserver_qfn((web_ex_func_cb)wifi_run, (void *)((uint32) wifi_cfg.mode), 200);
+ else ifcmp("mode") wifi_cfg.mode = val;
+ else ifcmp("bgn") wifi_cfg.bgn = val;
+ else ifcmp("lflg") wifi_cfg.load_flg = val;
+ else ifcmp("sflg") wifi_cfg.save_flg = val;
+ else ifcmp("txpow") wifi_cfg.tx_pwr = val;
+ else ifcmp("adpt") wifi_cfg.adaptivity = val;
+ else ifcmp("country") wifi_cfg.country_code = val;
+ // .. mac wifi_set_mac_address()
+
+// else ifcmp("scan") {
+// web_conn->web_disc_par = val;
+// web_conn->web_disc_cb = (web_func_disc_cb)wifi_start_scan;
+// }
+ else ifcmp("save") { write_wifi_cfg(val); }
+ else ifcmp("ap_") {
+ cstr+=3;
+ ifcmp("ssid") {
+ if(pvar[0]!='\0') {
+ int len = os_strlen(pvar);
+ if(len > NDIS_802_11_LENGTH_SSID) {
+ len = NDIS_802_11_LENGTH_SSID;
+ }
+ os_memset(wifi_ap_cfg.ssid, 0, sizeof(wifi_ap_cfg.ssid));
+ os_memcpy(wifi_ap_cfg.ssid, pvar, len);
+#ifdef USE_NETBIOS
+// netbios_set_name(wlan_ap_netifn, wifi_ap_cfg.ssid);
+#endif
+ }
+ }
+ else ifcmp("psw") {
+ int len = os_strlen(pvar);
+ if(len > IW_PASSPHRASE_MAX_SIZE) {
+ len = IW_PASSPHRASE_MAX_SIZE;
+ }
+ os_memset(wifi_ap_cfg.password, 0, sizeof(wifi_ap_cfg.password));
+ os_memcpy(wifi_ap_cfg.password, pvar, len);
+ }
+ else ifcmp("chl") wifi_ap_cfg.channel = val;
+ else ifcmp("mcns") wifi_ap_cfg.max_sta = val;
+ else ifcmp("auth") wifi_ap_cfg.security = val; // =1 IDX_SECURITY_WPA2_AES_PSK, =0 IDX_SECURITY_OPEN
+ else ifcmp("hssid") wifi_ap_cfg.ssid_hidden = val;
+ else ifcmp("bint") wifi_ap_cfg.beacon_interval = val;
+#if LWIP_NETIF_HOSTNAME
+ else ifcmp("hostname") {
+ int len = os_strlen(pvar);
+ if(len >= LWIP_NETIF_HOSTNAME_SIZE) {
+ len = LWIP_NETIF_HOSTNAME_SIZE-1;
+ }
+ if(len) {
+ os_memset(lwip_host_name[1], 0, LWIP_NETIF_HOSTNAME_SIZE);
+ os_memcpy(lwip_host_name[1], pvar, len);
+ }
+ netbios_set_name(WLAN_AP_NETIF_NUM, lwip_host_name[1]);
+ if(wifi_cfg.save_flg & BID_AP_HOSTNAME) {
+ WEB_SRV_QFNK x;
+ x.fnc = write_wifi_cfg;
+ x.param = (void *)BID_AP_HOSTNAME;
+ xQueueSendToBack(xQueueWebSrv, &x, 0);
+ }
+ }
+#endif
+ else ifcmp("dhcp") wifi_ap_dhcp.mode = val;
+ else ifcmp("ip") wifi_ap_dhcp.ip = ipaddr_addr(pvar);
+ else ifcmp("gw") wifi_ap_dhcp.gw = ipaddr_addr(pvar);
+ else ifcmp("msk") wifi_ap_dhcp.mask = ipaddr_addr(pvar);
+// else ifcmp("mac") strtomac(pvar, wifi_ap_cfg.macaddr);
+// else ifcmp("sip") wifi_ap_dhcp.start_ip = ipaddr_addr(pvar);
+// else ifcmp("eip") wifi_ap_dhcp.end_ip = ipaddr_addr(pvar);
+#if DEBUGSOO > 2
+ else os_printf(" - none! ");
+#endif
+ }
+ else ifcmp("st_") {
+ cstr+=3;
+ ifcmp("arec") wifi_st_cfg.autoreconnect = val;
+ else ifcmp("rect") wifi_st_cfg.reconnect_pause = val;
+ else ifcmp("ssid") {
+ if(pvar[0]!='\0') {
+ int len = os_strlen(pvar);
+ if(len > NDIS_802_11_LENGTH_SSID) {
+ len = NDIS_802_11_LENGTH_SSID;
+ }
+ os_memset(wifi_st_cfg.ssid, 0, sizeof(wifi_st_cfg.ssid));
+ os_memcpy(wifi_st_cfg.ssid, pvar, len);
+ }
+ }
+ else ifcmp("psw") {
+ int len = os_strlen(pvar);
+ if(len > IW_PASSPHRASE_MAX_SIZE) {
+ len = IW_PASSPHRASE_MAX_SIZE;
+ }
+ os_memset(wifi_st_cfg.password, 0, sizeof(wifi_st_cfg.password));
+ os_memcpy(wifi_st_cfg.password, pvar, len);
+ }
+ else ifcmp("auth") wifi_st_cfg.security = val;
+ else ifcmp("bssid") strtomac(pvar, wifi_st_cfg.bssid);
+ else ifcmp("sbss") wifi_st_cfg.flg = val;
+ else ifcmp("sleep") wifi_st_cfg.sleep = val;
+ else ifcmp("dtim") wifi_st_cfg.dtim = val;
+#if LWIP_NETIF_HOSTNAME
+ else ifcmp("hostname") {
+ int len = os_strlen(pvar);
+ if(len >= LWIP_NETIF_HOSTNAME_SIZE) {
+ len = LWIP_NETIF_HOSTNAME_SIZE-1;
+ }
+ if(len) {
+ os_memset(lwip_host_name[0], 0, LWIP_NETIF_HOSTNAME_SIZE);
+ os_memcpy(lwip_host_name[0], pvar, len);
+ netbios_set_name(WLAN_ST_NETIF_NUM, lwip_host_name[0]);
+ }
+ if(wifi_cfg.save_flg & BID_ST_HOSTNAME) {
+ WEB_SRV_QFNK x;
+ x.fnc = write_wifi_cfg;
+ x.param = (void *)BID_ST_HOSTNAME;
+ x.pause_ms = 0;
+ xQueueSendToBack(xQueueWebSrv, &x, 0);
+ }
+ }
+#endif
+ else ifcmp("dhcp") wifi_st_dhcp.mode = val;
+ else ifcmp("ip") wifi_st_dhcp.ip = ipaddr_addr(pvar);
+ else ifcmp("gw") wifi_st_dhcp.gw = ipaddr_addr(pvar);
+ else ifcmp("msk") wifi_st_dhcp.mask = ipaddr_addr(pvar);
+// else ifcmp("mac") strtomac(pvar, wifi_st_cfg.mac);
+// else ifcmp("sbss") wifi_st_cfg.bssidx = val;
+#if DEBUGSOO > 5
+ else os_printf(" - none!\n");
+#endif
+ }
+#if DEBUGSOO > 5
+ else os_printf(" - none!\n");
+#endif
+ }
+#if WEB_DEBUG_FUNCTIONS
+ else if(web_conn->bffiles[0]==WEBFS_WEBCGI_HANDLE && CheckSCB(SCB_GET)) {
+ ifcmp("hexdmp") {
+#if DEBUGSOO > 5
+ os_printf("hexdmp(%p)\n", val);
+#endif
+ if(val > 0) {
+ if(cstr[6]=='d') ts_conn->flag.user_option1 = 1;
+ else ts_conn->flag.user_option1 = 0;
+ uint32 x = ahextoul(cstr+7);
+ web_conn->udata_start = x;
+ web_conn->udata_stop = val + web_conn->udata_start;
+#if DEBUGSOO > 5
+ os_printf("start=%p, stop=%p\n", web_conn->udata_start, web_conn->udata_stop);
+#endif
+ web_conn->fileType = HTTP_TXT;
+ SetSCB(SCB_RETRYCB | SCB_FCALBACK);
+ SetNextFunSCB(web_hexdump);
+ };
+ }
+ else ifcmp("flash") {
+ cstr+=5;
+ if(*cstr == '_') {
+ cstr++;
+ ifcmp("all") {
+ web_conn->udata_start = 0;
+ web_conn->udata_stop = spi_flash_real_size();
+ web_conn->fileType = HTTP_BIN;
+ SetSCB(SCB_RETRYCB | SCB_FCALBACK);
+ SetNextFunSCB(web_get_flash);
+ }
+ else ifcmp("sec_") {
+ web_conn->udata_start = ahextoul(cstr+4) << 12;
+ web_conn->udata_stop = web_conn->udata_start + FLASH_SECTOR_SIZE*val;
+ web_conn->fileType = HTTP_BIN;
+ SetSCB(SCB_RETRYCB | SCB_FCALBACK);
+ SetNextFunSCB(web_get_flash);
+ }
+ else ifcmp("disk") {
+ web_conn->udata_start = WEBFS_base_addr();
+ web_conn->udata_stop = web_conn->udata_start + WEBFS_curent_size();
+ web_conn->fileType = HTTP_BIN;
+ SetSCB(SCB_RETRYCB | SCB_FCALBACK);
+ SetNextFunSCB(web_get_flash);
+ }
+ else tcp_put('?');
+ }
+ else {
+ web_conn->fileType = HTTP_BIN;
+ SetSCB(SCB_RETRYCB | SCB_FCALBACK);
+ SetNextFunSCB(web_get_flash);
+ }
+ }
+ else ifcmp("bin_ram") {
+ web_conn->fileType = HTTP_BIN;
+ SetSCB(SCB_RETRYCB | SCB_FCALBACK);
+ SetNextFunSCB(web_get_ram);
+ }
+#if DEBUGSOO > 5
+ else os_printf(" - none! ");
+#endif
+ }
+#endif // #if WEB_DEBUG_FUNCTIONS
+#if DEBUGSOO > 5
+ else os_printf(" - none! ");
+#endif
+}
+
+#endif // USE_WEB
diff --git a/RTLGDB/Project/web/web_srv.c b/RTLGDB/Project/web/web_srv.c
new file mode 100644
index 0000000..2f846cf
--- /dev/null
+++ b/RTLGDB/Project/web/web_srv.c
@@ -0,0 +1,2076 @@
+/******************************************************************************
+ * FileName: webserver.c
+ * Description: Small WEB server + WebSocket
+ * Author: pvvx
+ * ver1.0 25/12/2014 SDK 0.9.4
+ * ver1.1 02/04/2015 SDK 1.0.0
+ * ver2.0 14/14/2017 RTL871x
+*******************************************************************************/
+#include "user_config.h"
+#ifdef USE_WEB
+#include "autoconf.h"
+#include "FreeRTOS.h"
+#include "task.h"
+#include "diag.h"
+#include "lwip/tcp.h"
+#include "tcpsrv/tcp_srv_conn.h"
+#include "web_srv_int.h"
+#include "web_utils.h"
+#include "flash_eep.h"
+#include "device_lock.h"
+#include "webfs/webfs.h"
+#include "sys_cfg.h"
+#include "wifi_api.h"
+#include "rtl8195a/rtl_libc.h"
+#include "esp_comp.h"
+
+#ifdef WEBSOCKET_ENA
+#include "web_websocket.h"
+#endif
+
+#ifdef USE_CAPTDNS
+#include "captdns.h"
+#endif
+
+#ifdef USE_OVERLAY
+#include "overlay.h"
+#endif
+
+#define USE_WEB_NAGLE // https://en.wikipedia.org/wiki/Nagle%27s_algorithm
+#define MIN_REQ_LEN 7 // Minimum length for a valid HTTP/0.9 request: "GET /\r\n" -> 7 bytes
+#define CRLF "\r\n"
+
+#define max_len_buf_write_flash 2048 // размер буфера при записи flash. Увеличение/уменньшение размера (до сектора 4096) ускорения не дает (1..2%)
+
+//#define mMIN(a, b) ((ab)?a:b)
+#undef atoi
+#define atoi(s) rom_atoi(s)
+
+static void web_print_headers(HTTP_CONN *CurHTTP, TCP_SERV_CONN *ts_conn) ICACHE_FLASH_ATTR ;
+
+//static void webserver_discon(void *arg) ICACHE_FLASH_ATTR;
+//static void webserver_recon(void *arg, sint8 err) ICACHE_FLASH_ATTR;
+static void webserver_send_fdata(TCP_SERV_CONN *ts_conn) ICACHE_FLASH_ATTR;
+static void web_int_disconnect(TCP_SERV_CONN *ts_conn) ICACHE_FLASH_ATTR;
+static bool webserver_open_file(HTTP_CONN *CurHTTP, TCP_SERV_CONN *ts_conn) ICACHE_FLASH_ATTR;
+static void webserver_file_ext(HTTP_CONN *CurHTTP, uint8 *pfname) ICACHE_FLASH_ATTR;
+
+const char http_default_file[] ICACHE_RODATA_ATTR = "index.html";
+const char web_cgi_fname[] ICACHE_RODATA_ATTR = "web.cgi";
+const char fsupload_fname[] ICACHE_RODATA_ATTR = "fsupload";
+#ifdef USE_CAPTDNS
+const char ncsi_txt_fname[] ICACHE_RODATA_ATTR = "ncsi.txt";
+//const char generate_204_fname[] ICACHE_RODATA_ATTR = "generate_204";
+const char *HTTPHost ="Host:";
+#define sizeHTTPHost 5
+#endif
+#define ProtectedFilesName "protect"
+
+#define MAX_NO_DATA_BUF_SIZE (8192) // if(ts_conn->sizei > MAX_NO_DATA_BUF_SIZE) CurHTTP->httpStatus = 418; // 418: Out of Coffee
+
+QueueHandle_t xQueueWebSrv;
+
+/****************************************************************************
+ Section:
+ File and Content Type Settings
+ ***************************************************************************/
+ // File type extensions corresponding to HTTP_FILE_TYPE
+static const char *httpFileExtensions[] = {
+ "txt", // HTTP_TXT
+ "html", // HTTP_HTML
+ "cgi", // HTTP_CGI
+ "xml", // HTTP_XML
+ "css", // HTTP_CSS
+ "ico", // HTTP_ICO
+ "gif", // HTTP_GIF
+ "png", // HTTP_PNG
+ "jpg", // HTTP_JPG
+ "svg", // HTTP_SVG
+ "js", // HTTP_JAVA
+ "swf", // HTTP_SWF
+ "wav", // HTTP_WAV
+ "pdf", // HTTP_PDF
+ "zip", // HTTP_ZIP
+ "bin", // HTTP_BIN
+ "\0\0\0" // HTTP_UNKNOWN
+};
+
+// Content-type strings corresponding to HTTP_FILE_TYPE
+static const char *httpContentTypes[] = {
+ "text/plain", // HTTP_TXT "txt",
+ "text/html", // HTTP_HTM "htm",
+ "magnus-internal/cgi", // HTTP_CGI "cgi",
+ "text/xml", // HTTP_XML "xml",
+ "text/css", // HTTP_CSS "css",
+ "image/vnd.microsoft.icon", // HTTP_ICO "ico",
+ "image/gif", // HTTP_GIF "gif",
+ "image/png", // HTTP_PNG "png",
+ "image/jpeg", // HTTP_JPG "jpg",
+ "image/svg+xml", // HTTP_SVG "svg",
+ "text/javascript", // HTTP_JAVA "js",
+ "application/x-shockwave-flash", // HTTP_SWF "swf",
+ "audio/x-wave", // HTTP_WAV "wav",
+ "application/pdf", // HTTP_PDF "pdf",
+ "application/zip", // HTTP_ZIP "zip",
+ "application/octet-stream", // HTTP_BIN "bin",
+ "" // HTTP_UNKNOWN
+};
+/****************************************************************************
+ Section:
+ Commands and Server Responses
+ ***************************************************************************/
+const char HTTPresponse_200_head[] ICACHE_RODATA_ATTR = "OK";
+const char HTTPresponse_302_head[] ICACHE_RODATA_ATTR = "Found";
+const char HTTPresponse_304_head[] ICACHE_RODATA_ATTR = "Not Modified";
+const char HTTPresponse_400_head[] ICACHE_RODATA_ATTR = "Bad Request";
+const char HTTPresponse_401_head[] ICACHE_RODATA_ATTR = "Unauthorized\r\nWWW-Authenticate: Basic realm=\"Protected%u\"";
+const char HTTPresponse_404_head[] ICACHE_RODATA_ATTR = "Not found";
+const char HTTPresponse_411_head[] ICACHE_RODATA_ATTR = "Length Required";
+const char HTTPresponse_413_head[] ICACHE_RODATA_ATTR = "Request Entity Too Large";
+const char HTTPresponse_414_head[] ICACHE_RODATA_ATTR = "Request-URI Too Long";
+const char HTTPresponse_418_head[] ICACHE_RODATA_ATTR = "I'm a teapot";
+const char HTTPresponse_429_head[] ICACHE_RODATA_ATTR = "Too Many Requests\r\nRetry-After: 30";
+const char HTTPresponse_500_head[] ICACHE_RODATA_ATTR = "Internal Server Error";
+const char HTTPresponse_501_head[] ICACHE_RODATA_ATTR = "Not Implemented\r\nAllow: GET, POST";
+
+const char HTTPresponse_401_content[] ICACHE_RODATA_ATTR = "401 Unauthorized: Password required\r\n";
+const char HTTPresponse_404_content[] ICACHE_RODATA_ATTR = "404: File not found\r\n";
+const char HTTPresponse_411_content[] ICACHE_RODATA_ATTR = "411 The request must have a content length\r\n";
+const char HTTPresponse_413_content[] ICACHE_RODATA_ATTR = "413 Request Entity Too Large: There's too many letters :)\r\n";
+const char HTTPresponse_414_content[] ICACHE_RODATA_ATTR = "414 Request-URI Too Long: Buffer overflow detected\r\n";
+const char HTTPresponse_418_content[] ICACHE_RODATA_ATTR = "418: Out of Coffee\r\n";
+const char HTTPresponse_500_content[] ICACHE_RODATA_ATTR = "500 Internal Server Error\r\n";
+const char HTTPresponse_501_content[] ICACHE_RODATA_ATTR = "501 Not Implemented: Only GET and POST supported\r\n";
+
+// Initial response strings (Corresponding to HTTP_STATUS)
+static const HTTP_RESPONSE ICACHE_RODATA_ATTR HTTPResponse[] ICACHE_RODATA_ATTR = {
+ { 200, HTTP_RESP_FLG_NONE,
+ HTTPresponse_200_head,
+ NULL },
+ // успешный запрос. Если клиентом были запрошены какие-либо данные, то они находятся в заголовке и/или теле сообщения.
+ { 302, HTTP_RESP_FLG_NONE | HTTP_RESP_FLG_REDIRECT,
+ HTTPresponse_302_head,
+ NULL },
+// "HTTP/1.1 302 Found\r\nConnection: close\r\nLocation: ",
+ // 302 Found, 302 Moved Temporarily - запрошенный документ временно
+ // доступен по другому URI, указанному в заголовке в поле Location.
+ // Ртот РєРѕРґ может быть использован, например, РїСЂРё управляемом сервером
+ // согласовании содержимого. Некоторые клиенты некорректно ведут себя
+ // при обработке данного кода.
+ { 304, HTTP_RESP_FLG_NONE,
+ HTTPresponse_304_head,
+ NULL },
+///"304 Redirect: ", // If-Modified-Since If-None-Match
+ // сервер возвращает такой код, если клиент запросил документ методом GET,
+ // использовал заголовок If-Modified-Since или If-None-Match и документ
+ // не изменился с указанного момента. При этом сообщение сервера не должно содержать тела.
+ { 400, HTTP_RESP_FLG_FINDFILE,
+ HTTPresponse_400_head,
+ NULL} ,
+ // сервер обнаружил в запросе клиента синтаксическую ошибку.
+ { 401, HTTP_RESP_FLG_FINDFILE,
+ HTTPresponse_401_head,
+ HTTPresponse_401_content },
+ // для доступа к запрашиваемому ресурсу требуется аутентификация.
+ // В заголовке ответ должен содержать поле WWW-Authenticate с перечнем
+ // условий аутентификации. Клиент может повторить запрос,
+ // включив в заголовок сообщения поле Authorization с требуемыми для аутентификации данными.
+//"HTTP/1.1 403 Forbidden\r\nConnection: close\r\n\r\n403 Forbidden: SSL Required - use HTTPS\r\n"
+ { 404, HTTP_RESP_FLG_FINDFILE,
+ HTTPresponse_404_head,
+ HTTPresponse_404_content },
+ // Сервер понял запрос, но не нашёл соответствующего ресурса по указанному URI.
+ { 411, HTTP_RESP_FLG_FINDFILE,
+ HTTPresponse_411_head,
+ HTTPresponse_411_content },
+ // для указанного ресурса клиент должен указать Content-Length в заголовке запроса.
+ // Без указания этого поля не стоит делать повторную попытку запроса к серверу по данному URI.
+ // Такой ответ естественен для запросов типа POST и PUT.
+ // Например, если по указанному URI производится загрузка файлов, а на сервере стоит
+ // ограничение на их объём. Тогда разумней будет проверить в самом начале заголовок
+ // Content-Length и сразу отказать в загрузке, чем провоцировать бессмысленную нагрузку,
+ // разрывая соединение, когда клиент действительно пришлёт слишком объёмное сообщение.
+ { 413, HTTP_RESP_FLG_FINDFILE,
+ HTTPresponse_413_head,
+ HTTPresponse_413_content },
+ // возвращается в случае, если сервер отказывается обработать запрос
+ // по причине слишком большого размера тела запроса. Сервер может закрыть соединение,
+ // чтобы прекратить дальнейшую передачу запроса.
+ { 414, HTTP_RESP_FLG_FINDFILE,
+ HTTPresponse_414_head,
+ HTTPresponse_414_content },
+ // сервер не может обработать запрос из-за слишком длинного указанного URL.
+ // Такую ошибку можно спровоцировать, например, когда клиент пытается передать длинные
+ // параметры через метод GET, а не POST.
+ { 429, HTTP_RESP_FLG_NONE,
+ HTTPresponse_429_head,
+ NULL },
+ // клиент попытался отправить слишком много запросов за короткое время, что может указывать,
+ // например, на попытку DoS-атаки. Может сопровождаться заголовком Retry-After, указывающим,
+ // через какое время можно повторить запрос.
+ { 501, HTTP_RESP_FLG_FINDFILE,
+ HTTPresponse_501_head,
+ HTTPresponse_501_content },
+ // сервер не поддерживает возможностей, необходимых для обработки запроса.
+ // Типичный ответ для случаев, когда сервер не понимает указанный в запросе метод. + см 405
+ { 418, HTTP_RESP_FLG_FINDFILE,
+ HTTPresponse_418_head,
+ HTTPresponse_418_content },
+ // http://en.wikipedia.org/wiki/Hyper_Text_Coffee_Pot_Control_Protocol
+ { 500, HTTP_RESP_FLG_END,
+ HTTPresponse_500_head,
+ HTTPresponse_500_content }
+ // любая внутренняя ошибка сервера, которая не входит в рамки остальных ошибок класса.
+};
+const char HTTPfsupload[] ICACHE_RODATA_ATTR = "";
+#define sizeHTTPfsupload 220
+const char HTTPdefault[] ICACHE_RODATA_ATTR = "RTL871X Built-in Web server ©
";
+#define sizeHTTPdefault 73
+const char HTTPfserror[] ICACHE_RODATA_ATTR = "Web-disk error. Upload the WEBFiles.bin!
";
+#define sizeHTTPfserror 62
+
+const char HTTPAccessControlAllowOrigin[] ICACHE_RODATA_ATTR = "Access-Control-Allow-Origin: *\r\n";
+// const uint8 *HTTPCacheControl = "Cache-Control:";
+const char *HTTPContentLength = "Content-Length:";
+#define sizeHTTPContentLength 15
+// const uint8 *HTTPConnection = "Connection: ";
+// #define sizeHTTPConnection 12
+// const uint8 *HTTPkeepalive = "keep-alive";
+// #define sizeHTTPkeepalive 10
+// const uint8 *HTTPIfNoneMatch = "If-None-Match:"
+// #define sizeHTTPIfNoneMatch 14
+const char *HTTPContentType = "Content-Type:";
+#define sizeHTTPContentType 13
+const char *HTTPmultipartformdata = "multipart/form-data";
+#define sizeHTTPmultipartformdata 19
+const char *HTTPboundary = "boundary=";
+#define sizeHTTPboundary 9
+const char *HTTPAuthorization = "Authorization:";
+#define sizeHTTPAuthorization 14
+const char *HTTPCookie = "Cookie:";
+#define sizeHTTPCookie 7
+
+/******************************************************************************
+ * FunctionName : Close_web_conn
+ * Description : Free ts_conn
+ * Parameters : struct TCP_SERV_CONN
+ * Returns : none
+*******************************************************************************/
+static void ICACHE_FLASH_ATTR Close_web_conn(TCP_SERV_CONN *ts_conn)
+{
+ WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
+ int i = 0;
+ do {
+ if(web_conn->bffiles[i] != WEBFS_INVALID_HANDLE) {
+#if DEBUGSOO > 1
+ os_printf("cf%d ", web_conn->bffiles[i]);
+#endif
+ if(web_conn->bffiles[i] <= WEBFS_MAX_HANDLE) WEBFSClose(web_conn->bffiles[i]);
+ web_conn->bffiles[i] = WEBFS_INVALID_HANDLE;
+ };
+ i++;
+ }while(i < 4);
+ ClrSCB(SCB_FOPEN | SCB_FGZIP | SCB_FCALBACK);
+}
+/******************************************************************************
+ * FunctionName : ReNew_web_conn
+ * Description :
+ * Parameters : struct TCP_SERV_CONN
+ * Returns : none
+*******************************************************************************/
+static WEB_SRV_CONN * ICACHE_FLASH_ATTR ReNew_web_conn(TCP_SERV_CONN *ts_conn)
+{
+ WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
+ if(web_conn == NULL) {
+ web_conn = (WEB_SRV_CONN *)os_zalloc(sizeof(WEB_SRV_CONN));
+ if(web_conn != NULL) {
+ web_conn->bffiles[0] = WEBFS_INVALID_HANDLE;
+ web_conn->bffiles[1] = WEBFS_INVALID_HANDLE;
+ web_conn->bffiles[2] = WEBFS_INVALID_HANDLE;
+ web_conn->bffiles[3] = WEBFS_INVALID_HANDLE;
+ // web_conn->webflag = 0; //zalloc
+ // web_conn->func_web_cb = NULL; //zalloc
+ OpenSCB(); // сбросить флаги
+ ts_conn->linkd = (void *)web_conn;
+ };
+ }
+ return web_conn;
+}
+//=============================================================================
+// Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==\n"
+// The resulting string is then encoded using the RFC2045-MIME variant of Base64,
+// except not limited to 76 uint8/line
+// /ssl/crypto/ssl_crypto_misc.c:
+// EXP_FUNC int STDCALL base64_decode(const uint8 *in, int len, uint8_t *out, int *outlen);
+// Username and password are combined into a string "username:password"
+static uint8 ICACHE_FLASH_ATTR CheckAuthorization(uint8* base64str)
+{
+ uint8 *pcmp = base64str;
+ int len = 0;
+ while(*pcmp++ >= '+') len++;
+// struct softap_config apcfg;
+ uint8 pbuf[77];
+ int declen = 76;
+ if((len >= 4)&&(len <= 128)
+ &&(base64decode(base64str, len, pbuf, &declen))) {
+ pbuf[declen]='\0';
+#if DEBUGSOO > 1
+ os_printf("'%s' ", pbuf);
+#endif
+ return UserAuthorization(pbuf, declen);
+ };
+ return 0;
+}
+//=============================================================================
+#define web_parse_cookie(CurHTTP, ts_conn) web_parse_vars(ts_conn, (CurHTTP)->pcookie, (CurHTTP)->cookie_len, '\0', ';')
+#define web_parse_uri_vars(CurHTTP, ts_conn) web_parse_vars(ts_conn, (CurHTTP)->puri, (CurHTTP)->uri_len, '?', '&')
+#define web_parse_content(CurHTTP, ts_conn) web_parse_vars(ts_conn, (CurHTTP)->pcontent, (CurHTTP)->content_len, '\0', '&')
+static void ICACHE_FLASH_ATTR web_parse_vars(TCP_SERV_CONN *ts_conn, uint8 *vars, uint32 vars_len, uint8 start_char, uint8 end_char)
+{
+ if(vars == NULL || vars_len == 0) return;
+ uint8 *pcmp;
+ if(start_char) {
+ pcmp = cmpcpystr(NULL, vars, '\0', start_char, vars_len); // find start_char if available
+ start_char = '\0';
+ } else pcmp = vars - 1;
+ while(pcmp != NULL) {
+ uint16 len = vars_len - (pcmp - vars);
+ uint8 *pcmd = pcmp;
+ pcmp = cmpcpystr(pcmp, pcmp + 1, start_char, '=', len); // skip spaces before variable name
+ if(pcmp == NULL) break;
+ urldecode(pcmd, pcmd, len, len);
+ len = vars_len - (pcmp - vars);
+ uint8 *pvar = pcmp;
+ pcmp = cmpcpystr(pcmp, pcmp + 1, '\0', end_char, len);
+ if(pcmd[0] != '\0') {
+ urldecode(pvar, pvar, len, len);
+ web_int_vars(ts_conn, pcmd, pvar);
+ }
+ }
+}
+//=============================================================================
+// Разбор имени файла и перевод в вид относительного URI.
+// (выкидывание HTTP://Host)
+// Проверка на обращение в папку или имя файла требующее пароль
+//=============================================================================
+static void ICACHE_FLASH_ATTR
+web_parse_fname(HTTP_CONN *CurHTTP, TCP_SERV_CONN *ts_conn)
+{
+ if(CurHTTP->puri == NULL)
+ return;
+
+ if(CurHTTP->uri_len < 2)
+ { // = "/"?
+ CurHTTP->pFilename[0] = CurHTTP->puri[0];
+ return;
+ }
+
+ {
+ uint8 cbuf[FileNameSize+16];
+ uint8 *pcbuf = cbuf;
+ urldecode(pcbuf, CurHTTP->puri, sizeof(cbuf) - 1, CurHTTP->uri_len);
+ if(rom_xstrcmp((char *)pcbuf, "HTTP://")||(rom_xstrcmp((char *)pcbuf, "http://"))) {
+ pcbuf += 7;
+ uint8 *pcmp = os_strchr((char *)pcbuf, '/');
+ if(pcmp != NULL) pcbuf = pcmp;
+ };
+ cmpcpystr(CurHTTP->pFilename, pcbuf, '\0', '?', FileNameSize);
+ }
+
+ { // Проверка на обращение в папку или имя файла требующее пароль
+ uint8 *pcmp = web_strnstr(CurHTTP->pFilename, ProtectedFilesName, os_strlen(CurHTTP->pFilename));
+ if(pcmp != NULL)
+ {
+ WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
+#if USE_WEB_AUTH_LEVEL
+ pcmp += sizeof(ProtectedFilesName) - 1;
+ web_conn->auth_realm = atoi(pcmp) + 1;
+ printf("[%s] ar%d ", pcmp, web_conn->auth_realm);
+// web_conn->auth_realm = WEB_AUTH_LEVEL_USER;
+#endif
+ SetSCB(SCB_AUTH);
+ }
+ }
+}
+//=============================================================================
+//=============================================================================
+uint8 * ICACHE_FLASH_ATTR head_find_ctr(HTTP_CONN *CurHTTP, const uint8 * c, int clen, int dlen)
+{
+ if(CurHTTP->head_len < clen + dlen + 2) return NULL; // + "\r\n"
+ uint8 * pstr = web_strnstr((char *)CurHTTP->phead, c, CurHTTP->head_len);
+ if(pstr != NULL) {
+ pstr += clen;
+ uint8 *pend = web_strnstr(pstr, CRLF, CurHTTP->phead + CurHTTP->head_len - pstr);
+ if(pend == NULL) {
+ CurHTTP->httpStatus = 400; // 400 Bad Request
+ return NULL;
+ }
+ while(*pstr == ' ' && pstr < pend) pstr++;
+ if(pend - pstr < dlen) {
+ CurHTTP->httpStatus = 400; // 400 Bad Request
+ return NULL;
+ }
+ }
+ return pstr;
+}
+//=============================================================================
+// Func: parse_header
+// Разбирает докачан или нет заголовок HTTP, что там принято, GET или POST,
+// открывает файл и проверяет content, если это POST и не прием файла.
+//=============================================================================
+static bool ICACHE_FLASH_ATTR
+parse_header(HTTP_CONN *CurHTTP, TCP_SERV_CONN *ts_conn)
+{
+ WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
+ CurHTTP->httpStatus = 501; // 501 Not Implemented (not a GET or POST command)
+
+ uint8 *pstr = ts_conn->pbufi;
+ uint8 *pend = &ts_conn->pbufi[ts_conn->sizei];
+ CurHTTP->pcontent = pend;
+
+ if(pstr == NULL) {
+ CurHTTP->httpStatus = 500; // 500 Internal Server Error
+ return false;
+ };
+ if(ts_conn->sizei < MIN_REQ_LEN) return false; // 501 Not Implemented (not a GET or POST command)
+ uint8 *pnext = web_strnstr(pstr, CRLF, ts_conn->sizei); // "\r\n"
+// if(pnext != NULL) *pnext = '\0';
+ if(pnext == NULL) {
+ CurHTTP->httpStatus = 400; // 400 Bad Request
+ return false;
+ };
+ pnext += 2;
+ if(pnext - pstr < MIN_REQ_LEN) return false; // 501 размер строки запроса менее "GET /"
+ if(os_strncmp(pstr, "GET ", 4) == 0) {
+ SetSCB(SCB_GET);
+ CurHTTP->httpStatus = 200;
+ pstr += 4;
+ }
+ else if(os_strncmp(pstr, "POST ", 5) == 0) {
+ SetSCB(SCB_POST);
+ CurHTTP->httpStatus = 200;
+ pstr += 5;
+ }
+ else return false; // 501 Not Implemented (not a GET or POST command)
+ CurHTTP->puri = pstr;
+ CurHTTP->uri_len = pnext - pstr;
+
+ if(CurHTTP->uri_len > 10) { // "/ HTTP/1.0\r\n"
+ pstr = web_strnstr(CurHTTP->puri, " HTTP/", CurHTTP->uri_len);
+ if(pstr != NULL) {
+ if((pstr[7] == '.')&&(pstr[6] <= '9')&&(pstr[6] >= '0')&&(pstr[8] >= '0')&&(pstr[8] <= '9'))
+ CurHTTP->httpver = ((pstr[6]-'0')<<4) + pstr[8]-'0';
+ // else CurHTTP->ver = 0x00;
+ };
+ };
+#if DEBUGSOO > 3
+ os_printf("http_ver=%02x ", CurHTTP->httpver);
+#endif
+ if(CurHTTP->httpver < 0x10) { // HTTP/0.9 ?
+ if(CheckSCB(SCB_POST)) {
+ CurHTTP->httpStatus = 400; // 400 HTTP/0.9 does not support POST
+ return false; // HTTP/0.9
+ };
+ };
+ // здесь уже надо глядеть - следует или нет докачивать данные
+ pstr = web_strnstr(pnext-2, CRLF CRLF, pend - pnext + 2 ); // find "\r\n\r\n"
+ if(pstr == NULL) return true; // докачивать!
+ // разбираем дальше Header, раз уже скачан
+ pstr += 2;
+ if(pstr != pnext) { // есть Headers
+ CurHTTP->phead = pnext;
+ CurHTTP->head_len = pstr - pnext;
+ if(CheckSCB(SCB_POST)){
+ pstr += 2;
+ CurHTTP->pcontent = pstr;
+ CurHTTP->content_len = pend - pstr;
+ };
+ };
+ if(!CheckSCB(SCB_FOPEN)) { // файл уже открыт? нет
+ web_parse_fname(CurHTTP, ts_conn);
+ if(!webserver_open_file(CurHTTP, ts_conn)) {
+ CurHTTP->httpStatus = 404; // "404: File not found"
+ return false; //
+ };
+ };
+ if((CurHTTP->phead == NULL)||(CurHTTP->head_len == 0)) {
+ // если требуется авторизация, но нет передачи пароля...
+ if(CheckSCB(SCB_AUTH)) CurHTTP->httpStatus = 401; // 401 Unauthorized
+ return false; // нет Header
+ };
+ if(CheckSCB(SCB_POST)) {
+ pstr = head_find_ctr(CurHTTP, HTTPContentLength, sizeHTTPContentLength, 1);
+ if(pstr == NULL || CurHTTP->httpStatus != 200) {
+ CurHTTP->httpStatus = 411; // no "Content Length:", 411 Length Required
+ return false;
+ }
+ uint32 cnlen = atoi(pstr);
+#if DEBUGSOO > 1
+ os_printf("content_len = %d of %d ", cnlen, CurHTTP->content_len);
+#endif
+ if(cnlen) {
+ web_conn->content_len = cnlen; // запомнить размер, для приема файла
+ if(!CheckSCB(SCB_BNDR) && (CurHTTP->head_len > sizeHTTPContentType + sizeHTTPmultipartformdata + sizeHTTPboundary + 2 + 2)) { //"x\r\n"
+ pstr = head_find_ctr(CurHTTP, HTTPContentType, sizeHTTPContentType, sizeHTTPmultipartformdata + sizeHTTPboundary + 2);
+ if(CurHTTP->httpStatus != 200) return false;
+ if(pstr != NULL) {
+ pend = web_strnstr(pstr, CRLF, CurHTTP->phead + CurHTTP->head_len - pstr);
+ pstr = web_strnstr(pstr, HTTPmultipartformdata, pend - pstr);
+ if(pstr != NULL) {
+ pstr += sizeHTTPmultipartformdata;
+ pstr = web_strnstr(pstr, HTTPboundary, pend - pstr);
+ if(pstr != NULL) {
+ // сохраним этот "мультипаспорт" (с) 5-ый элемент :)
+ pstr += sizeHTTPboundary;
+ HTTP_UPLOAD *pupload = (HTTP_UPLOAD *)os_zalloc(sizeof(HTTP_UPLOAD));
+ if(pupload == NULL) {
+ CurHTTP->httpStatus = 500; // 500 Internal Server Error
+ return false;
+ }
+ uint8 x = *pend;
+ *pend = '\0';
+#if DEBUGSOO > 4
+ os_printf("[%s] ", pstr);
+#endif
+ rtl_memcpy(pupload->boundary, pstr, MAXLENBOUNDARY);
+ *pend = x;
+ pupload->sizeboundary = os_strlen(pupload->boundary);
+ ts_conn->pbufo = (uint8 *)pupload;
+ SetSCB(SCB_BNDR);
+// if(cnlen > ((pupload->sizeboundary * 2) + 18)) {
+ SetSCB(SCB_RXDATA);
+// }
+ };
+ };
+ };
+ };
+ if((!CheckSCB(SCB_BNDR)) && cnlen > CurHTTP->content_len) { // обычный контент и недокачан заголовок? да.
+ CurHTTP->content_len = cnlen;
+#if DEBUGSOO > 2
+ os_printf("wait content ");
+#endif
+ CurHTTP->httpStatus = 413; // 413 Request Entity Too Large // пока так
+ return true; // докачивать
+ };
+ }
+ else CurHTTP->content_len = cnlen; // уточнить, что Content Length = 0
+ };
+ if(CheckSCB(SCB_AUTH)) {
+ pstr = head_find_ctr(CurHTTP, HTTPAuthorization, sizeHTTPAuthorization, 5 + 3); // "Authorization: Basic 1234\r\n"
+ if(pstr == NULL || CurHTTP->httpStatus != 200) {
+ CurHTTP->httpStatus = 401; // 401 Unauthorized
+ return false;
+ }
+ if(os_strncmp(pstr, "Basic", 5) == 0) { // The authorization method and a space i.e. "Basic" is then put before the encoded string.
+ pstr += 5;
+ while(*pstr == ' ') pstr++;
+#if USE_WEB_AUTH_LEVEL
+ web_conn->auth_level = CheckAuthorization(pstr);
+#if DEBUGSOO > 1
+ os_printf("%u?%u ", web_conn->auth_level, web_conn->auth_realm);
+#endif
+ if(web_conn->auth_level >= web_conn->auth_realm)
+ ClrSCB(SCB_AUTH);
+#else
+ if(CheckAuthorization(pstr))
+ ClrSCB(SCB_AUTH);
+#endif
+ else {
+ CurHTTP->httpStatus = 401; // 401 Unauthorized
+ return false;
+ };
+ }
+ else {
+ CurHTTP->httpStatus = 401; // 401 Unauthorized
+ return false;
+ };
+ };
+
+ if(CurHTTP->head_len > sizeHTTPCookie + 4) { // "Cookie: a=\r\n"
+ pstr = head_find_ctr(CurHTTP, HTTPCookie, sizeHTTPCookie, 2);
+ if(pstr != NULL) {
+ pend = web_strnstr(pstr, CRLF, CurHTTP->phead + CurHTTP->head_len - pstr);
+ if(pend != NULL) {
+ CurHTTP->pcookie = pstr;
+ CurHTTP->cookie_len = pend - pstr;
+#if DEBUGSOO > 3
+ *pend = '\0';
+ os_printf("cookie:[%s] ", pstr);
+ *pend = '\r';
+#endif
+ }
+#if DEBUGSOO > 3
+ else os_printf("cookie not crlf! ");
+#endif
+ };
+ };
+#ifdef WEBSOCKET_ENA
+ if(CheckSCB(SCB_GET) && web_conn->bffiles[0] == WEBFS_WEBCGI_HANDLE) {
+#if DEBUGSOO > 3
+ os_printf("hdlen=%d ", CurHTTP->head_len);
+#endif
+ if(CurHTTP->head_len > sizeHTTPUpgrade + sizeHTTPwebsocket + 2 + sizeHTTPSecWebSocketKey + minsizeWebSocketKey + 2) { // + "\r\n"
+ pstr = head_find_ctr(CurHTTP, HTTPUpgrade, sizeHTTPUpgrade, sizeHTTPwebsocket);
+ if(CurHTTP->httpStatus != 200) return false;
+ if(pstr != NULL) {
+ if(!rom_xstrcmp(word_to_lower_case(pstr), HTTPwebsocket)) {
+ CurHTTP->httpStatus = 400; // 400 Bad Request
+ return false;
+ }
+ pstr = head_find_ctr(CurHTTP, HTTPSecWebSocketKey, sizeHTTPSecWebSocketKey, minsizeWebSocketKey);
+ if(pstr == NULL || CurHTTP->httpStatus != 200) return false;
+ {
+ if(WebSocketAcceptKey(CurHTTP->pFilename, pstr)) SetSCB(SCB_WEBSOC);
+ }
+ }
+ }
+ }
+#endif
+ return false;
+}
+/******************************************************************************
+ * FunctionName : web_inc_fp
+ * Parameters : fp
+*******************************************************************************/
+static void ICACHE_FLASH_ATTR web_inc_fp(WEB_SRV_CONN *web_conn, WEBFS_HANDLE fp)
+{
+ if(web_conn->bffiles[3] != WEBFS_INVALID_HANDLE) {
+ #if DEBUGSOO > 1
+ os_printf("cf%d ", web_conn->bffiles[3]);
+ #endif
+ if(web_conn->bffiles[3] <= WEBFS_MAX_HANDLE) {
+ web_conn->content_len -= WEBFSGetBytesRem(web_conn->bffiles[3]);
+ WEBFSClose(web_conn->bffiles[3]);
+ }
+ };
+ web_conn->bffiles[3] = web_conn->bffiles[2];
+ web_conn->bffiles[2] = web_conn->bffiles[1];
+ web_conn->bffiles[1] = web_conn->bffiles[0];
+ web_conn->bffiles[0] = fp;
+ SetSCB(SCB_FOPEN); // файл открыт
+}
+/******************************************************************************
+ * FunctionName : web_inc_fopen
+ * Description : web include file open
+ * Parameters : struct
+ * Returns : true - open OK
+*******************************************************************************/
+bool ICACHE_FLASH_ATTR web_inc_fopen(TCP_SERV_CONN *ts_conn, uint8 *cFile)
+{
+ WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
+ if(CheckSCB(SCB_FOPEN) && (!CheckSCB(SCB_FCALBACK))) { // файл уже открыт и он не парсится?
+ return false; // такое не поддерживается в "~inc:filename~"
+ };
+ WEBFS_HANDLE fp = WEBFSOpen(cFile);
+#if DEBUGSOO > 1
+ os_printf("of%d[%s] ", fp, cFile);
+#endif
+ if(fp != WEBFS_INVALID_HANDLE) {
+ if(fatCache.flags & WEBFS_FLAG_HASINDEX) SetSCB(SCB_FCALBACK); // файл надо парсить
+ web_conn->content_len += WEBFSGetBytesRem(fp); // указать размер файла для вывода
+ if(fatCache.flags & WEBFS_FLAG_ISZIPPED) {
+ if(CheckSCB(SCB_FOPEN)) { // файл уже открыт и "~inc:filename~" не поддерживает GZIP!
+ WEBFSClose(fp);
+#if DEBUGSOO > 1
+ os_printf("Not inc GZIP! ");
+#endif
+ return false;
+ };
+ SetSCB(SCB_FGZIP); // файл сжат GZIP
+ }
+ }
+ else { // File not found
+ return false;
+ };
+ web_inc_fp(web_conn, fp);
+ return true;
+};
+/******************************************************************************
+ * FunctionName : web_inc_file
+ * Description : web include file close
+ * Parameters : struct
+ * Returns : true - все файлы закрыты
+*******************************************************************************/
+bool ICACHE_FLASH_ATTR web_inc_fclose(WEB_SRV_CONN *web_conn)
+{
+ if(web_conn->bffiles[0] != WEBFS_INVALID_HANDLE) {
+#if DEBUGSOO > 1
+ os_printf("cf%d ", web_conn->bffiles[0]);
+#endif
+ if(web_conn->bffiles[0] <= WEBFS_MAX_HANDLE) {
+ WEBFSClose(web_conn->bffiles[0]);
+ ClrSCB(SCB_FGZIP);
+ }
+ web_conn->bffiles[0] = web_conn->bffiles[1];
+ web_conn->bffiles[1] = web_conn->bffiles[2];
+ web_conn->bffiles[2] = web_conn->bffiles[3];
+ web_conn->bffiles[3] = WEBFS_INVALID_HANDLE;
+ if(web_conn->bffiles[0] != WEBFS_INVALID_HANDLE) return false;
+ };
+ ClrSCB(SCB_FOPEN | SCB_FGZIP | SCB_FCALBACK);
+ return true; // больше нет файлов
+};
+/******************************************************************************
+ * FunctionName : webserver_open_file
+ * Description : Compare to known extensions to determine Content-Type
+ * Parameters : filename -- file name
+ * Returns : 1 - open, 0 - no
+*******************************************************************************/
+static void ICACHE_FLASH_ATTR webserver_file_ext(HTTP_CONN *CurHTTP, uint8 *pfname)
+{
+ uint8 *pfext = NULL;
+ while(*pfname >= ' ') if(*pfname++ == '.') pfext = pfname;
+ if(pfext != NULL) {
+ for(CurHTTP->fileType = HTTP_TXT; CurHTTP->fileType < HTTP_UNKNOWN; CurHTTP->fileType++)
+ if(rom_xstrcmp(pfext, httpFileExtensions[CurHTTP->fileType])) break;
+ };
+}
+/*----------------------------------------------------------------------*/
+#ifdef USE_CAPTDNS
+/* = flase, если включен redirect, и запрос от ip адреса из подсети AP,
+ * и Host name не равен aesp8266 или ip AP. */
+static bool ICACHE_FLASH_ATTR web_cdns_no_redir(HTTP_CONN *CurHTTP, TCP_SERV_CONN *ts_conn)
+{
+ if(syscfg.cfg.b.cdns_ena
+ && pcb_cdns != NULL
+ &&((ts_conn->pcb->remote_ip.addr ^ info.ap_ip) & info.ap_mask) == 0
+ && CurHTTP->phead != NULL
+ && CurHTTP->head_len != 0) {
+ uint8 * ps = head_find_ctr(CurHTTP, HTTPHost, sizeHTTPHost, 7);
+ if(ps != NULL) {
+#if DEBUGSOO > 1
+ os_printf("Host: '%s' ", ps);
+#endif
+ uint8 strip[4*4];
+ os_sprintf_fd(strip, IPSTR, IP2STR(&info.ap_ip));
+ if((rom_xstrcmp(ps, HostNameLocal) == 0) && (rom_xstrcmp(ps, strip) == 0)) {
+ rtl_sprintf(CurHTTP->pFilename, httpHostNameLocal, HostNameLocal); // "http://esp8266/"
+ WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
+ SetSCB(SCB_REDIR);
+ return false;
+ }
+ }
+ }
+ return true;
+}
+#endif
+/******************************************************************************
+ * FunctionName : webserver_open_file
+ * Description : Open file
+ * Parameters : filename -- file name
+ * Returns : 1 - open, 0 - no
+*******************************************************************************/
+static bool ICACHE_FLASH_ATTR webserver_open_file(HTTP_CONN *CurHTTP, TCP_SERV_CONN *ts_conn)
+{
+ WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
+ uint8 pbuf[MAX_FILE_NAME_SIZE];
+ uint8 *pstr = pbuf;
+ if(CurHTTP->pFilename[0] == '/')
+ {
+ if(CurHTTP->pFilename[1] == '\0')
+ {
+ if(isWEBFSLocked)
+ {
+ web_inc_fp(web_conn, WEBFS_NODISK_HANDLE); // желательно дописать ответ, что нет диска.
+ web_conn->content_len = sizeHTTPfserror;
+ CurHTTP->fileType = HTTP_HTML;
+#if DEBUGSOO > 1
+ os_printf("of%d[%s] ", web_conn->webfile, CurHTTP->pFilename);
+#endif
+ return true;
+ }
+ else {
+#ifdef USE_CAPTDNS
+ if(web_cdns_no_redir(CurHTTP, ts_conn)) rom_xstrcpy(pstr, http_default_file);
+ else return false;
+#else
+ rom_xstrcpy(pstr, http_default_file);
+#endif
+ }
+ }
+ else
+ {
+ rtl_memcpy(pstr, &CurHTTP->pFilename[1], MAX_FILE_NAME_SIZE-1);
+ if(rom_xstrcmp(pstr, web_cgi_fname))
+ {
+ web_inc_fp(web_conn, WEBFS_WEBCGI_HANDLE);
+ web_conn->content_len = sizeHTTPdefault;
+#if USE_WEB_AUTH_LEVEL
+// web_conn->auth_realm = WEB_AUTH_LEVEL_USER;
+// SetSCB(SCB_AUTH);
+#endif
+ CurHTTP->fileType = HTTP_HTML;
+#if DEBUGSOO > 1
+ os_printf("of%d[%s] ", web_conn->webfile, CurHTTP->pFilename);
+#endif
+ return true;
+ }
+ else if(rom_xstrcmp(pstr, fsupload_fname))
+ {
+#if USE_WEB_AUTH_LEVEL
+ web_conn->auth_realm = WEB_AUTH_LEVEL_WEBFS;
+#endif
+ SetSCB(SCB_AUTH);
+ web_inc_fp(web_conn, WEBFS_UPLOAD_HANDLE);
+ web_conn->content_len = sizeHTTPfsupload;
+ CurHTTP->fileType = HTTP_HTML;
+#if DEBUGSOO > 1
+ os_printf("of%d[%s] ", web_conn->webfile, CurHTTP->pFilename);
+#endif
+ return true;
+ }
+ }
+ if(isWEBFSLocked) return false;
+ // поиск файла на диске
+ if(!web_inc_fopen(ts_conn, pstr)) {
+ uint32 i = os_strlen(pbuf);
+ if(i + sizeof(http_default_file) < MAX_FILE_NAME_SIZE - 1)
+ {
+ // добавить к имени папки "/index.htm"
+ pbuf[i] = '/';
+ rom_xstrcpy(&pbuf[i+1], http_default_file);
+ if(!web_inc_fopen(ts_conn, pstr))
+ {
+#ifdef USE_CAPTDNS
+ web_cdns_no_redir(CurHTTP, ts_conn);
+#endif
+ return false;
+ }
+ };
+ };
+ // Compare to known extensions to determine Content-Type
+ webserver_file_ext(CurHTTP, pstr);
+ return true;
+ };
+ return false; // файл не открыт
+}
+/******************************************************************************
+*******************************************************************************/
+static void ICACHE_FLASH_ATTR web_send_fnohanle(TCP_SERV_CONN *ts_conn) {
+ WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
+ uint32 pdata = 0;
+// uint8 pbuf[mMAX(mMAX(sizeHTTPdefault,sizeHTTPfserror), sizeHTTPfsupload)];
+ uint32 size = 0;
+ switch(web_conn->webfile) {
+ case WEBFS_WEBCGI_HANDLE:
+ pdata = (uint32)((void *)HTTPdefault);
+ size = sizeHTTPdefault;
+ break;
+ case WEBFS_UPLOAD_HANDLE:
+ pdata = (uint32)((void *)HTTPfsupload);
+ size = sizeHTTPfsupload;
+ break;
+ case WEBFS_NODISK_HANDLE:
+ pdata = (uint32)((void *)HTTPfserror);
+ size = sizeHTTPfserror;
+ break;
+ }
+ if(pdata != 0 && size != 0) {
+// spi_flash_read(pdata & MASK_ADDR_FLASH_ICACHE_DATA, pbuf, size);
+ tcpsrv_int_sent_data(ts_conn, (uint8 *) pdata, size);
+ }
+#if DEBUGSOO > 1
+ os_printf("%u ", size);
+#endif
+ SetSCB(SCB_FCLOSE|SCB_DISCONNECT);
+}
+/******************************************************************************
+*******************************************************************************/
+static int ICACHE_FLASH_ATTR web_find_cbs(uint8 * chrbuf, uint32 len) {
+ uint32 i;
+ for(i = 0; i < len; i++) if(chrbuf[i] == '~') return i;
+ return -1;
+}
+/******************************************************************************
+ * FunctionName : webserver_send_fdata
+ * Description : Sent callback function to call for this espconn when data
+ * is successfully sent
+ * Parameters : arg -- Additional argument to pass to the callback function
+ * Returns : none
+*******************************************************************************/
+static void ICACHE_FLASH_ATTR webserver_send_fdata(TCP_SERV_CONN *ts_conn) {
+ WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
+ if(web_conn->webfile == WEBFS_INVALID_HANDLE) {
+ SetSCB(SCB_FCLOSE|SCB_DISCONNECT);
+ return;
+ }
+#if DEBUGSOO > 1
+ os_printf("send: ");
+#endif
+#ifdef SET_CPU_CLK_SPEED
+// set_cpu_clk();
+#endif
+ web_conn->msgbufsize = tcp_sndbuf(ts_conn->pcb);
+
+#if DEBUGSOO > 5
+ os_printf("sndbuf=%u ", web_conn->msgbufsize);
+#endif
+
+ if (web_conn->msgbufsize < MIN_SEND_SIZE) {
+#if DEBUGSOO > 1
+ os_printf("sndbuf=%u! ", web_conn->msgbufsize);
+ if(ts_conn->flag.wait_sent) os_printf("wait_sent! "); // блок передан?
+#endif
+ ts_conn->pcb->flags &= ~TF_NODELAY;
+ tcpsrv_int_sent_data(ts_conn, (uint8 *)ts_conn, 0);
+ return;
+ }
+ if((web_conn->webfile > WEBFS_MAX_HANDLE)&&(!CheckSCB(SCB_RETRYCB))) {
+ web_send_fnohanle(ts_conn);
+ return;
+ }
+ web_conn->msgbufsize = mMIN(MAX_SEND_SIZE, web_conn->msgbufsize);
+ uint8 *pbuf = (uint8 *) os_malloc(web_conn->msgbufsize);
+ if (pbuf == NULL) {
+#if DEBUGSOO > 0
+ os_printf("out of memory - disconnect!\n");
+#endif
+ SetSCB(SCB_FCLOSE|SCB_DISCONNECT);
+ return;
+ };
+ web_conn->msgbuf = pbuf;
+ web_conn->msgbuflen = 0;
+ if (CheckSCB(SCB_CHUNKED)) { // is chunked
+ web_conn->msgbuf += RESCHKS_SEND_SIZE;
+ web_conn->msgbufsize -= RESCHK_SEND_SIZE;
+ };
+ if(CheckSCB(SCB_FCALBACK) == 0) { // передача файла без парсинга
+ // Get/put as many bytes as possible
+ web_conn->msgbuflen = WEBFSGetArray(web_conn->webfile, web_conn->msgbuf, web_conn->msgbufsize);
+ if(web_conn->msgbuflen < web_conn->msgbufsize ) SetSCB(SCB_FCLOSE | SCB_DISCONNECT);
+ }
+ else { // парсинг потока передачи
+ do { // начинаем с пустого буфера
+ if(CheckSCB(SCB_RETRYCB)) { // повторный callback? да
+#if DEBUGSOO > 2
+ os_printf("rcb ");
+#endif
+ if(web_conn->func_web_cb != NULL) web_conn->func_web_cb(ts_conn);
+ if(CheckSCB(SCB_RETRYCB)) break; // повторить ещё раз? да.
+ }
+ else {
+ uint8 *pstr = &web_conn->msgbuf[web_conn->msgbuflen]; // указатель в буфере
+ // запомнить указатель в файле. ftell(fp)
+ uint32 max = mMIN(web_conn->msgbufsize - web_conn->msgbuflen, SCB_SEND_SIZE); // читаем по 128 байт ?
+ uint32 len = WEBFSGetArray(web_conn->webfile, pstr, max);
+ // прочитано len байт в буфер по указателю &sendbuf[msgbuflen]
+ if(len) { // есть байты для передачи, ищем string "~calback~"
+ int cmp = web_find_cbs(pstr, len);
+ if(cmp >= 0) { // найден calback
+ // откат файла
+ WEBFSStubs[web_conn->webfile].addr -= len;
+ WEBFSStubs[web_conn->webfile].bytesRem += len;
+ // передвинуть указатель в файле на считанные байты с учетом маркера, без добавки длины для передачи
+ WEBFSStubs[web_conn->webfile].addr += cmp+1;
+ WEBFSStubs[web_conn->webfile].bytesRem -= cmp+1;
+ // это второй маркер?
+ if(CheckSCB(SCB_FINDCB)) { // в файле найден закрывающий маркер calback
+ ClrSCB(SCB_FINDCB); // прочитали string calback-а
+ if(cmp != 0) { // это дубль маркера ? нет.
+ // запустить calback
+ pstr[cmp] = '\0'; // закрыть string calback-а
+ if(!os_memcmp((void*)pstr, "inc:", 4)) { // "inc:file_name"
+ if(!web_inc_fopen(ts_conn, &pstr[4])) {
+ tcp_strcpy_fd("file not found!");
+ };
+ }
+ else web_int_callback(ts_conn, pstr);
+ }
+ else { // Дубль маркера.
+ web_conn->msgbuflen++; // передать только маркер ('~')
+ };
+ }
+ else {
+ SetSCB(SCB_FINDCB); // в файле найден стартовый маркер calback
+ web_conn->msgbuflen += cmp; // передать до стартового маркера calback
+ };
+ }
+ else { // просто данные
+ ClrSCB(SCB_FINDCB);
+ if(len < max) {
+ if(web_inc_fclose(web_conn)) SetSCB(SCB_FCLOSE | SCB_DISCONNECT); // файл(ы) закончилсь совсем? да.
+ };
+ web_conn->msgbuflen += len; // добавить кол-во считанных байт для передачи.
+ };
+ }
+ else if(web_inc_fclose(web_conn)) SetSCB(SCB_FCLOSE | SCB_DISCONNECT); // файл(ы) закончилсь совсем? да.
+ }; // not SCB_RETRYCB
+ } // набираем буфер
+ while((web_conn->msgbufsize - web_conn->msgbuflen >= SCB_SEND_SIZE)&&(!CheckSCB(SCB_FCLOSE | SCB_RETRYCB | SCB_DISCONNECT)));
+ };
+#if DEBUGSOO > 3
+ os_printf("#%04x %d ", web_conn->webflag, web_conn->msgbuflen);
+#elif DEBUGSOO > 1
+ os_printf("%u ", web_conn->msgbuflen);
+#endif
+ if(web_conn->msgbuflen) {
+ web_conn->content_len -= web_conn->msgbuflen; // пока только для инфы
+ if(CheckSCB(SCB_CHUNKED)) { // greate chunked
+ uint8 cbuf[16];
+ static const char chunks[] ICACHE_RODATA_ATTR = "\r\n%X\r\n";
+ unsigned int len = rtl_sprintf(cbuf, chunks, web_conn->msgbuflen);
+ web_conn->msgbuf -= len;
+ rtl_memcpy(web_conn->msgbuf, cbuf, len);
+ web_conn->msgbuflen += len;
+ if(CheckSCB(SCB_FCLOSE)) { // close file? -> add 'end chunked'
+ tcp_strcpy_fd("\r\n0\r\n\r\n");
+ };
+ };
+ ts_conn->pcb->flags |= TF_NODELAY;
+ tcpsrv_int_sent_data(ts_conn, web_conn->msgbuf, web_conn->msgbuflen);
+ };
+ os_free(pbuf);
+ web_conn->msgbuf = NULL;
+}
+/******************************************************************************
+ * FunctionName : web_print_headers
+ * Description : Print HTTP Response Header
+ * Parameters : *
+ * Returns : none
+*******************************************************************************/
+static void ICACHE_FLASH_ATTR
+web_print_headers(HTTP_CONN *CurHTTP, TCP_SERV_CONN *ts_conn)
+{
+ WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
+ HTTP_RESPONSE *CurResp = (HTTP_RESPONSE *)HTTPResponse;
+#if DEBUGSOO > 3
+ os_printf("prh#%04x,%d,%d ", web_conn->webflag, CurHTTP->httpStatus, CurHTTP->fileType);
+#endif
+ web_conn->msgbuf = (uint8 *)os_malloc(HTTP_SEND_SIZE);
+ if(web_conn->msgbuf == NULL)
+ {
+#if DEBUGSOO == 1
+ os_printf("web: out of memory!\n");
+#elif DEBUGSOO > 1
+ os_printf("out of memory! ");
+#endif
+ SetSCB(SCB_FCLOSE | SCB_DISCONNECT);
+ return;
+ }
+ web_conn->msgbufsize = HTTP_SEND_SIZE;
+ web_conn->msgbuflen = 0;
+ if(CheckSCB(SCB_REDIR)) {
+ CurHTTP->httpStatus = 302; // редирект
+ }
+#ifdef WEBSOCKET_ENA
+ if(CheckSCB(SCB_WEBSOC) && CurHTTP->httpStatus == 200) {
+#if DEBUGSOO > 1
+ CurHTTP->httpStatus = 101;
+#endif
+ tcp_puts(WebSocketHTTPOkKey, CurHTTP->pFilename);
+ }
+ else {
+#endif
+ while(!(CurResp->flag & HTTP_RESP_FLG_END)) {
+ if(CurResp->status == CurHTTP->httpStatus) break;
+ CurResp++;
+ };
+ tcp_puts_fd("HTTP/1.1 %u ", CurResp->status);
+#if USE_WEB_AUTH_LEVEL
+ if(CurResp->status == 401) tcp_puts_fd(CurResp->headers, web_conn->auth_realm);
+#else
+ if (CurResp->status == 401) tcp_puts_fd(CurResp->headers);
+#endif
+ else tcp_strcpy(CurResp->headers);
+ tcp_strcpy_fd("\r\nServer: " WEB_NAME_VERSION "\r\nConnection: close\r\n");
+ if(CheckSCB(SCB_REDIR)) {
+ tcp_puts_fd("Location: %s\r\n\r\n", CurHTTP->pFilename);
+ ts_conn->flag.pcb_time_wait_free = 1; // закрыть соединение
+ SetSCB(SCB_DISCONNECT);
+ }
+ else {
+ if(CurResp->status != 200) {
+ web_inc_fclose(web_conn);
+ ClrSCB(SCB_FCALBACK | SCB_FGZIP | SCB_CHUNKED | SCB_RXDATA | SCB_FCLOSE);
+ if(CurResp->flag & HTTP_RESP_FLG_FINDFILE) {
+ os_sprintf_fd(CurHTTP->pFilename, "/%u.htm", CurResp->status);
+ webserver_open_file(CurHTTP, ts_conn);
+ // CurHTTP->httpStatus = CurResp->status; // вернуть статус!
+ };
+ }
+ if((!CheckSCB(SCB_FOPEN)) && (CurResp->default_content != NULL) ) {
+ tcp_puts_fd("%s %u\r\n%s %s\r\n\r\n", HTTPContentLength, rtl_strlen(CurResp->default_content),
+ HTTPContentType, httpContentTypes[HTTP_TXT]);
+ tcp_strcpy(CurResp->default_content);
+ SetSCB(SCB_DISCONNECT);
+ }
+ else if(CheckSCB(SCB_FOPEN)) {
+ if(web_conn->content_len) {
+ // Указать, что данные могут пользовать все (очень актуально для XML, ...)
+ tcp_strcpy_fd("Access-Control-Allow-Origin: *\r\n");
+ if(CurHTTP->fileType != HTTP_UNKNOWN) {
+ if(web_conn->bffiles[0] == WEBFS_WEBCGI_HANDLE && CheckSCB(SCB_FCALBACK)) CurHTTP->fileType = web_conn->fileType;
+ tcp_puts_fd("Content-Type: %s\r\n", httpContentTypes[CurHTTP->fileType]);
+ };
+ // Output the cache-control + ContentLength
+ if(CheckSCB(SCB_FCALBACK)) { // длина неизветсна
+ // file is callback index
+ tcp_strcpy_fd("Cache-Control: no-store, no-cache, must-revalidate, max-age=0\r\n");
+ if(CurHTTP->httpver >= 0x11) SetSCB(SCB_CHUNKED);
+ }
+ else { // длина изветсна
+ tcp_puts_fd("%s %d\r\n", HTTPContentLength, web_conn->content_len);
+ if(CurResp->status == 200 && (!isWEBFSLocked) && web_conn->bffiles[0] != WEBFS_WEBCGI_HANDLE) {
+ // lifetime (sec) of static responses as string 60*60*24*14=1209600"
+ tcp_puts_fd("Cache-Control: smax-age=%d\r\n", FILE_CACHE_MAX_AGE_SEC);
+ }
+ else {
+ tcp_strcpy_fd("Cache-Control: no-store, no-cache, must-revalidate, max-age=0\r\n");
+ }
+ };
+ if(CheckSCB(SCB_FGZIP)) {
+ // Output the gzip encoding header if needed
+ tcp_strcpy_fd("Content-Encoding: gzip\r\n");
+ }
+ else if(CheckSCB(SCB_CHUNKED)) {
+ tcp_strcpy_fd("Transfer-Encoding: chunked\r\n");
+ }
+ if(!CheckSCB(SCB_CHUNKED)) tcp_strcpy_fd(CRLF);
+ }
+ else {
+ tcp_puts_fd("%s 0\r\n\r\n", HTTPContentLength);
+ SetSCB(SCB_FCLOSE|SCB_DISCONNECT);
+ }
+ }
+ else SetSCB(SCB_DISCONNECT);
+ } // CheckSCB(SCB_REDIR)
+#ifdef WEBSOCKET_ENA
+ }
+#endif
+#if DEBUGSOO > 3
+ os_printf("#%04x (%d) %d ", web_conn->webflag, web_conn->msgbuflen, CurHTTP->httpStatus);
+ web_conn->msgbuf[web_conn->msgbuflen] = 0;
+ os_printf("\n2?%d[%s]\n", web_conn->msgbuflen, web_conn->msgbuf);
+#elif DEBUGSOO > 1
+ os_printf("head[%d]:%d ", web_conn->msgbuflen, CurHTTP->httpStatus);
+#endif
+ if(web_conn->msgbuflen) {
+ if(CheckSCB(SCB_DISCONNECT)) SetSCB(SCB_CLOSED);
+ tcpsrv_int_sent_data(ts_conn, web_conn->msgbuf, web_conn->msgbuflen);
+#ifdef USE_WEB_NAGLE
+ ts_conn->flag.nagle_disabled = 1;
+#endif
+ };
+ os_free(web_conn->msgbuf);
+ web_conn->msgbuf = NULL;
+}
+/******************************************************************************/
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// РїРѕРёСЃРє boundary
+// 0 - разделитель (boundary) не найден, докачивать или ...
+// 1 - boundary найден
+// 200 - найден завершаюший boundary
+// 400 - неверный формат
+// ...
+//-----------------------------------------------------------------------------
+/* Пример M-Explorer: Load blk len: 399
+-----------------------------7df22f37711be\r\n
+Content-Disposition: form-data; name="test"; filename="readme.txt"\r\n
+Content-Type: text/plain\r\n\r\n
+1234567890\r\n
+-----------------------------7df22f37711be\r\n
+Content-Disposition: form-data; name="start"\r\n\r\n
+0x1B000\r\n
+-----------------------------7df22f37711be\r\n
+Content-Disposition: form-data; name="stop"\r\n\r\n
+0x1B000\r\n
+-----------------------------7df22f37711be--\r\n */
+/* Пример Google Chrome: Load blk len: 391
+------WebKitFormBoundaryugGNBVFOk6qxfe22\r\n
+Content-Disposition: form-data; name="test"; filename="readme.txt"\r\n
+Content-Type: text/plain\r\n\r\n
+1234567890\r\n
+------WebKitFormBoundaryugGNBVFOk6qxfe22\r\n
+Content-Disposition: form-data; name="start"\r\n\r\n
+0x1B000\r\n
+------WebKitFormBoundaryugGNBVFOk6qxfe22\r\n
+Content-Disposition: form-data; name="stop"\r\n\r\n
+0x1B000\r\n
+------WebKitFormBoundaryugGNBVFOk6qxfe22--\r\n */
+//-----------------------------------------------------------------------------
+const char crlf_end_boundary[] ICACHE_RODATA_ATTR = "--" CRLF;
+static int ICACHE_FLASH_ATTR find_boundary(HTTP_UPLOAD *pupload, uint8 *pstr, uint32 len)
+{
+ int x = len - 6 - pupload->sizeboundary;
+ if(x <= 0) return 0; // разделитель (boundary) не найден - докачивать буфер
+ int i;
+ uint8 *pcmp;
+ for(i = 0; i <= x; i++) {
+ if(pstr[i] == '-' && pstr[i+1] == '-') {
+ pcmp = pstr + i;
+// if((pstr + len - pcmp) < pupload->sizeboundary + 6) return 0; // разделитель (boundary) не найден - докачивать буфер
+ pupload->pbndr = pcmp; // указатель на заголовок boundary (конец блока данных);
+ pcmp += 2;
+ if(os_memcmp(pcmp, pupload->boundary, pupload->sizeboundary)) return 0; // разделитель (boundary) не найден
+ pcmp += pupload->sizeboundary;
+ if(rom_xstrcmp(pcmp, crlf_end_boundary)) {
+ pcmp += 4;
+ pupload->pnext = pcmp; // указатель в заголовке boundary (описание новых данных);
+ return 200; // найден завершающий разделитель
+ }
+ if(pcmp[0] != '\r' || pcmp[1] != '\n') return 400; // неверный формат
+ pcmp += 2;
+ pupload->pnext = pcmp; // указатель в заголовке boundary (описание новых данных);
+ return 1;
+ };
+ };
+ return 0; // разделитель (boundary) не найден - докачивать буфер
+}
+//-----------------------------------------------------------------------------
+// Function: cmp_next_boundary
+// return:
+// 0 - разделитель (boundary) не найден, докачивать
+// 1 - далее обработка данных
+// 200 - найден завершающий разделитель: "\r\n--boundary--"
+// 400 - неизвестный формат content-а
+//-----------------------------------------------------------------------------
+const char disk_ok_filename[] ICACHE_RODATA_ATTR = "/disk_ok.htm";
+const char disk_err1_filename[] ICACHE_RODATA_ATTR = "/disk_er1.htm";
+const char disk_err2_filename[] ICACHE_RODATA_ATTR = "/disk_er2.htm";
+const char disk_err3_filename[] ICACHE_RODATA_ATTR = "/disk_er3.htm";
+const char sysconst_filename[] ICACHE_RODATA_ATTR = "sysconst";
+#ifdef USE_OVERLAY
+const char overlay_filename[] ICACHE_RODATA_ATTR = "overlay";
+#endif
+const char sector_filename[] ICACHE_RODATA_ATTR = "fsec_";
+#define sector_filename_size 5
+const char file_label[] ICACHE_RODATA_ATTR = "file";
+
+static int ICACHE_FLASH_ATTR upload_boundary(TCP_SERV_CONN *ts_conn) // HTTP_UPLOAD pupload, uint8 pstr, uint16 len)
+{
+ HTTP_UPLOAD *pupload = (HTTP_UPLOAD *)ts_conn->pbufo;
+ WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
+ if(pupload == NULL) return 500; // ошибка сервера
+ uint32 ret;
+ uint32 len;
+ uint8 *pnext;
+ uint8 *pstr;
+ while(web_conn->content_len && ts_conn->pbufi != NULL) {
+ pstr = ts_conn->pbufi;
+ len = ts_conn->sizei;
+#if DEBUGSOO > 4
+ os_printf("bufi[%u]%u, cont:%u ", ts_conn->sizei, ts_conn->cntri, web_conn->content_len);
+#endif
+ if(len < (8 + pupload->sizeboundary)) return 0; // разделитель (boundary) не влезет - докачивать буфер
+ switch(pupload->status) {
+ case 0: // РїРѕРёСЃРє boundary
+ {
+#if DEBUGSOO > 4
+ os_printf("find_bndr ");
+#endif
+ pnext = web_strnstr(pstr, CRLF CRLF , len);
+ if(pnext == NULL) return 0; // докачивать
+ len = pnext - pstr;
+ ret = find_boundary(pupload, pstr, len);
+#if DEBUGSOO > 4
+ os_printf("len=%u,ret=%u ", len, ret );
+#endif
+ if(ret != 1) return ret;
+ pstr = pupload->pnext; // +"\r\n" адрес за заголовком boundary
+ pupload->name[0] = '\0';
+ pupload->filename[0] = '\0';
+ pstr = web_strnstr(pstr, "name=", pnext - pstr);
+ if(pstr == NULL) return 400; // неизвестный формат content-а
+ pstr += 5;
+ if(pstr >= pnext) return 400; // неизвестный формат content-а
+ uint8 *pcmp = cmpcpystr(pupload->name, pstr, '"', '"', VarNameSize);
+ if(pcmp == NULL) {
+ pcmp = cmpcpystr(pupload->name, pstr, 0x22, 0x22, VarNameSize);
+ if(pcmp == NULL) return 400; // неизвестный формат content-а
+ };
+ pstr = pcmp;
+#if DEBUGSOO > 4
+ os_printf("name:'%s' ", pupload->name);
+#endif
+ if(pstr >= pnext) return 400; // неизвестный формат content-а
+ pcmp = web_strnstr(pstr, "filename=", pnext - pstr);
+ if(pcmp != NULL) {
+ pcmp += 9;
+ if(pcmp < pnext) {
+ if(cmpcpystr(pupload->filename, pcmp, '"', '"', VarNameSize) == NULL)
+ cmpcpystr(pupload->filename, pcmp, 0x22, 0x22, VarNameSize);
+ };
+#if DEBUGSOO > 1
+ if(pupload->filename[0]!= '\0') os_printf("filename:'%s' ", pupload->filename);
+#endif
+ };
+ len += 4;
+ pupload->status++;
+#if DEBUGSOO > 4
+ os_printf("trim#%u\n", len );
+#endif
+ ts_conn->cntri += len; // далее идут данные
+ if(!web_trim_bufi(ts_conn, &ts_conn->pbufi[len], ts_conn->sizei - len)) return 500;
+ web_conn->content_len -= len;
+ break;
+ }
+ case 1: // прием данных, первый заход, проверка форматов и т.д.
+ {
+#if DEBUGSOO > 4
+ os_printf("tst,fn='%s' ", pupload->filename);
+#endif
+ if(pupload->filename[0]!='\0') { // загрузка файла?
+ if(rom_xstrcmp(pupload->name, file_label)) { // !os_memcmp((void*)pupload->name, "file", 4)
+ if(len < sizeof(WEBFS_DISK_HEADER)) return 0; // докачивать
+ WEBFS_DISK_HEADER *dhead = (WEBFS_DISK_HEADER *)pstr;
+ if(dhead->id != WEBFS_DISK_ID || dhead->ver != WEBFS_DISK_VER
+ || (web_conn->content_len - pupload->sizeboundary - 8 < dhead->disksize)) {
+ if(isWEBFSLocked) return 400;
+ SetSCB(SCB_REDIR);
+ rom_xstrcpy(pupload->filename, disk_err1_filename); // rtl_memcpy(pupload->filename,"/disk_er1.htm\0",14); // неверный формат
+ return 200;
+ };
+ if(dhead->disksize > WEBFS_max_size()) {
+ if(isWEBFSLocked) return 400;
+ SetSCB(SCB_REDIR);
+ rom_xstrcpy(pupload->filename, disk_err2_filename); // rtl_memcpy(pupload->filename,"/disk_er2.htm\0",14); // не влезет
+ return 200;
+ };
+ pupload->fsize = dhead->disksize;
+ pupload->faddr = WEBFS_base_addr();
+#if DEBUGSOO > 4
+ os_printf("updisk[%u]=ok ", dhead->disksize);
+#endif
+ pupload->status = 3; // = 3 загрузка WebFileSystem во flash
+ isWEBFSLocked = true;
+ break;
+ }
+#ifdef USE_OVERLAY
+ else if(rom_xstrcmp(pupload->name, overlay_filename)) {
+ if(len < sizeof(struct SPIFlashHeader)) return 0; // докачивать
+ struct SPIFlashHeader *fhead = (struct SPIFlashHeader *)pstr;
+ if(web_conn->content_len - pupload->sizeboundary < sizeof(fhead)
+ || fhead->head.id != LOADER_HEAD_ID) {
+ if(isWEBFSLocked) return 400;
+ SetSCB(SCB_REDIR);
+ rom_xstrcpy(pupload->filename, disk_err1_filename); // rtl_memcpy(pupload->filename,"/disk_er1.htm\0",14); // неверный формат
+ return 200;
+ };
+ if(fhead->entry_point >= IRAM_BASE && ovl_call != NULL) {
+ ovl_call(0); // close прошлый оверлей
+ ovl_call = NULL;
+ }
+ pupload->start = fhead->entry_point;
+ pupload->segs = fhead->head.number_segs;
+ if(pupload->segs) {
+ pupload->fsize = sizeof(struct SPIFlashHeadSegment);
+ pupload->status = 5; // = 5 загрузка файла оверлея, начать с загрузки заголовка сегмента
+ }
+ else {
+ pupload->fsize = 0;
+ pupload->status = 4; // = 4 загрузка файла оверлея, запуск entry_point
+ }
+ //
+ len = sizeof(struct SPIFlashHeader);
+ ts_conn->cntri += len;
+ if(!web_trim_bufi(ts_conn, &ts_conn->pbufi[len], ts_conn->sizei - len)) return 500;
+ web_conn->content_len -= len;
+ //
+ break;
+ }
+#endif
+ else if(rom_xstrcmp(pupload->name, sysconst_filename)) {
+ pupload->fsize = FLASH_SECTOR_SIZE;
+ pupload->faddr = FLASH_RESERVED_DATA_BASE; // FLASH_SYSTEM_DATA_ADDR
+ pupload->status = 2; // = 2 загрузка файла во flash
+ break;
+ }
+ else if(rom_xstrcmp(pupload->name, sector_filename)) {
+ pupload->fsize = FLASH_SECTOR_SIZE;
+ pupload->faddr = ahextoul(&pupload->name[sector_filename_size]) << 12;
+ pupload->status = 2; // = 2 загрузка файла сектора во flash
+ break;
+ };
+ if(isWEBFSLocked) return 400;
+ SetSCB(SCB_REDIR);
+ rom_xstrcpy(pupload->filename, disk_err3_filename); // rtl_memcpy(pupload->filename,"/disk_er3.htm\0",14); // неизвестный тип
+ return 200;
+ }
+ else {
+ uint8 *pcmp = web_strnstr(pstr, CRLF, len);
+ if(pcmp == NULL) return 0; // докачивать
+ ret = find_boundary(pupload, pstr, len);
+#if DEBUGSOO > 4
+ os_printf("ret=%u ", ret );
+#endif
+ if((ret != 1 && ret != 200)) { // не найден конец или новый boundary?
+ return ret; // догружать
+ }
+ *pcmp = '\0';
+ web_int_vars(ts_conn, pupload->name, pstr);
+ if(ret == 200) return ret;
+ // найден следующий boundary
+ len = pupload->pbndr - ts_conn->pbufi;
+ pupload->status = 0; // = 0 найден следующий boundary
+#if DEBUGSOO > 4
+ os_printf("trim#%u\n", len );
+#endif
+ ts_conn->cntri += len; // далее идут данные
+ if(!web_trim_bufi(ts_conn, &ts_conn->pbufi[len], ts_conn->sizei - len)) return 500;
+ web_conn->content_len -= len;
+ break;
+ }
+// return 400;
+ }
+// default:
+ case 2: // загрузка файла во flash
+ case 3: // загрузка WebFileSystem во flash (скорость записи W25Q128 ~175 килобайт в сек, полный диск на 15,5МБ пишется 90..100 сек )
+ {
+#if DEBUGSOO > 4
+ os_printf("fdata ");
+#endif
+ uint32 block_size = mMIN(max_len_buf_write_flash + 8 + pupload->sizeboundary, web_conn->content_len);
+ if(ts_conn->sizei < block_size) return 0; // докачивать
+ ret = find_boundary(pupload, pstr, block_size);
+#if DEBUGSOO > 4
+ os_printf("ret=%u ", ret);
+#endif
+ if((ret == 1 || ret == 200)) { // найден конец или новый boundary?
+ len = mMIN(block_size, pupload->pbndr - 2 - ts_conn->pbufi);
+ }
+ else {
+ len = mMIN(max_len_buf_write_flash, web_conn->content_len - 8 - pupload->sizeboundary);
+ }
+#if DEBUGSOO > 4
+ os_printf("\nlen=%d, block_size=%d, content_len=%d, sizeboundary= %d, ret=%d, data = %d, load=%d", len, block_size, web_conn->content_len, pupload->sizeboundary, ret, pupload->pbndr - ts_conn->pbufi, ts_conn->sizei);
+#endif
+ if(pupload->fsize < len) block_size = pupload->fsize;
+ else block_size = len;
+ if(block_size) { // идут данные файла
+// tcpsrv_unrecved_win(ts_conn); // для ускорения, пока стрирается-пишется уже обновит окно (включено в web_rx_buf)
+
+ device_mutex_lock(RT_DEV_LOCK_FLASH);
+ if(pupload->faddr >= flash_get_size(&flashobj) && pupload->status == 3) {
+ if((pupload->faddr & 0x0000FFFF)==0) {
+
+#if DEBUGSOO > 2
+ os_printf("Clear flash page addr %p... ", pupload->faddr);
+#endif
+ flash_erase_block(&flashobj, pupload->faddr);
+ }
+ }
+ else if((pupload->faddr & 0x00000FFF) == 0) {
+#if DEBUGSOO > 2
+ os_printf("Clear flash sector addr %p... ", pupload->faddr);
+#endif
+ flash_erase_sector(&flashobj, pupload->faddr);
+ }
+#if DEBUGSOO > 2
+ os_printf("Write flash addr:%p[0x%04x]\n", pupload->faddr, block_size);
+#endif
+ flash_stream_write(&flashobj, pupload->faddr, (block_size + 3)&(~3), (uint8_t *)pstr);
+
+ device_mutex_unlock(RT_DEV_LOCK_FLASH);
+
+ pupload->fsize -= block_size;
+ pupload->faddr += block_size;
+ }
+#if DEBUGSOO > 4
+ os_printf("trim#%u\n", len);
+#endif
+ if(len) {
+ ts_conn->cntri += len;
+ if(!web_trim_bufi(ts_conn, &ts_conn->pbufi[len], ts_conn->sizei - len)) return 500;
+ web_conn->content_len -= len;
+ }
+#ifdef SET_CPU_CLK_SPEED
+// if(syscfg.cfg.b.hi_speed_enable) set_cpu_clk();
+#endif
+ if((ret == 1 || ret == 200)) { // найден конец или новый boundary?
+ if(pupload->status == 3) WEBFSInit();
+ if(pupload->fsize != 0) {
+ if(!isWEBFSLocked) {
+ SetSCB(SCB_REDIR);
+ rom_xstrcpy(pupload->filename, disk_err1_filename); // rtl_memcpy(pupload->filename,"/disk_er1.htm\0",14); // не всё передано или неверный формат
+ return 200;
+ }
+ return 400; // не всё передано или неверный формат
+ }
+ else {
+ if(!isWEBFSLocked) {
+ SetSCB(SCB_REDIR);
+ rom_xstrcpy(pupload->filename, disk_ok_filename); // rtl_memcpy(pupload->filename,"/disk_ok.htm\0",13);
+ };
+ };
+ if(ret == 1) pupload->status = 0; // = 0 найден следующий boundary
+ if(ret == 200) return ret;
+ }
+ break;
+ }
+#ifdef USE_OVERLAY
+ case 4: // загрузка данных/кода оверлея
+ case 5: // загрузка заголовка данных оверлея
+ {
+ uint32 block_size = mMIN(max_len_buf_write_flash + 8 + pupload->sizeboundary, web_conn->content_len);
+ if(ts_conn->sizei < block_size) return 0; // докачивать
+ ret = find_boundary(pupload, pstr, block_size);
+ if((ret == 1 || ret == 200)) { // найден конец или новый boundary?
+ len = mMIN(block_size, pupload->pbndr - 2 - ts_conn->pbufi);
+ }
+ else {
+ len = mMIN(max_len_buf_write_flash, web_conn->content_len - 8 - pupload->sizeboundary);
+ }
+ block_size = len;
+ while(block_size) {
+#if DEBUGSOO > 5
+ os_printf("blk:%d,st:%d,fs:%d,%d ", block_size, pupload->status, pupload->fsize, pupload->segs);
+#endif
+ if(pupload->status == 5) {
+ if(block_size >= sizeof(struct SPIFlashHeadSegment)) { // размер данных
+ if(pupload->segs) { //
+ rtl_memcpy(&pupload->faddr, pstr, 4);
+ rtl_memcpy(&pupload->fsize, &pstr[4], 4);
+#if DEBUGSOO > 4
+ os_printf("New seg ovl addr:%p[%p] ", pupload->faddr, pupload->fsize);
+#endif
+ }
+ }
+ else if(ret != 1 && ret != 200) { // не найден конец или boundary?
+ return 0; // докачивать
+ }
+ else {
+#if DEBUGSOO > 5
+ os_printf("err_load_fseg ");
+#endif
+// if(block_size < sizeof(struct SPIFlashHeadSegment)
+// || pupload->segs == 0 //
+// || pupload->fsize > USE_OVERLAY) {
+ if(!isWEBFSLocked) {
+ SetSCB(SCB_REDIR);
+ rom_xstrcpy(pupload->filename, disk_err1_filename); // rtl_memcpy(pupload->filename,"/disk_er1.htm\0",14); // не всё передано или неверный формат
+ return 200;
+ }
+ return 400; // не всё передано или неверный формат
+ }
+ pupload->segs--; // счет сегментов
+ pupload->status = 4; // загрузка данных/кода оверлея
+ pstr += sizeof(struct SPIFlashHeadSegment);
+ block_size -= sizeof(struct SPIFlashHeadSegment);
+ };
+ uint32 i = mMIN(pupload->fsize, block_size);
+ if(i) {
+#if DEBUGSOO > 1
+ os_printf("Wr:%p[%p] ", pupload->faddr, i);
+#endif
+ copy_s1d4((void *)pupload->faddr, pstr, i);
+ block_size -= i;
+ pupload->faddr += i;
+ pstr += i;
+ pupload->fsize -= i;
+ };
+ if(pupload->fsize == 0) {
+ if(pupload->segs) { // все сегменты загружены?
+ pupload->status = 5; // загрузка заголовка данных оверлея
+ }
+ else { // все сегменты загружены
+ block_size = 0;
+ break; // break while(block_size)
+ }
+ };
+ }; // while(block_size)
+ if(len) {
+ ts_conn->cntri += len;
+ if(!web_trim_bufi(ts_conn, &ts_conn->pbufi[len], ts_conn->sizei - len)) return 500;
+ web_conn->content_len -= len;
+ };
+ if((ret == 1 || ret == 200)) { // найден конец или новый boundary?
+#if DEBUGSOO > 5
+ os_printf("fs:%d,%d ", pupload->fsize, pupload->segs);
+#endif
+ if(pupload->fsize != 0 || pupload->segs != 0) { //
+ if(!isWEBFSLocked) {
+ SetSCB(SCB_REDIR);
+ rom_xstrcpy(pupload->filename, disk_err1_filename); // rtl_memcpy(pupload->filename,"/disk_er1.htm\0",14); // не всё передано или неверный формат
+ return 200;
+ }
+ return 400; // не всё передано или неверный формат
+ }
+ else {
+#if DEBUGSOO > 1
+ os_printf("Run%p ", pupload->start);
+#endif
+ if(pupload->start >= IRAM_BASE) {
+ ovl_call = (tovl_call *)pupload->start;
+ web_conn->web_disc_cb = (web_func_disc_cb)pupload->start; // адрес старта оверлея
+ web_conn->web_disc_par = 1; // параметр функции - инициализация
+ }
+ if(!isWEBFSLocked) {
+ SetSCB(SCB_REDIR);
+ rom_xstrcpy(pupload->filename, disk_ok_filename); // rtl_memcpy(pupload->filename,"/disk_ok.htm\0",13);
+ };
+ };
+ if(ret == 1) pupload->status = 0; // = 0 найден следующий boundary
+ if(ret == 200) return ret;
+ };
+ break;
+ };
+#endif
+ };
+ };
+ return 0; //
+}
+//-----------------------------------------------------------------------------
+// web_rx_buf
+//
+//-----------------------------------------------------------------------------
+static bool ICACHE_FLASH_ATTR web_rx_buf(HTTP_CONN *CurHTTP, TCP_SERV_CONN *ts_conn)
+{
+ WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
+ ts_conn->flag.rx_buf = 1; // указать, что всегда в режиме докачивать
+// CurHTTP->fileType = HTTP_UNKNOWN;
+// ts_conn->pbufi, ts_conn->cntri;
+#if DEBUGSOO > 3
+ os_printf("rx:%u[%u] ", web_conn->content_len, ts_conn->sizei);
+#endif
+ if(ts_conn->sizei == 0) return true; // докачивать
+ tcpsrv_unrecved_win(ts_conn);
+ int ret = upload_boundary(ts_conn);
+ if(ret > 1) {
+ CurHTTP->httpStatus = ret;
+ web_conn->content_len = 0;
+ if(ret == 200) {
+ if(CheckSCB(SCB_REDIR)) {
+ HTTP_UPLOAD *pupload = (HTTP_UPLOAD *)ts_conn->pbufo;
+ if(pupload != NULL) {
+ rtl_memcpy(CurHTTP->pFilename, pupload->filename, VarNameSize);
+// SetSCB(SCB_DISCONNECT);
+ }
+ }
+ else if((!isWEBFSLocked) && CheckSCB(SCB_FOPEN)
+ && web_conn->webfile <= WEBFS_MAX_HANDLE
+ && WEBFSGetFilename(web_conn->webfile, CurHTTP->pFilename, FileNameSize)) {
+ SetSCB(SCB_REDIR);
+// web_conn->content_len = WEBFSGetBytesRem(web_conn->webfile); // WEBFSGetSize(web_conn->webfile);
+// webserver_file_ext(CurHTTP, CurHTTP->pFilename);
+// return false; // ok 200 + file
+ }
+ }
+ SetSCB(SCB_DISCONNECT);
+ return false; // неизвестный content или end
+ }
+ else {
+#if DEBUGSOO > 2
+ os_printf("no boundary ");
+#endif
+ if(ts_conn->sizei > MAX_NO_DATA_BUF_SIZE) {
+ CurHTTP->httpStatus = 418; // 418: Out of Coffee
+ SetSCB(SCB_DISCONNECT);
+ return false; // неизвестный content или end
+ }
+ };
+ if(web_conn->content_len > ts_conn->cntri) return true; // докачивать
+ CurHTTP->httpStatus = 400;
+ SetSCB(SCB_DISCONNECT);
+ web_conn->content_len = 0;
+ return false; // неизвестный content
+}
+//-----------------------------------------------------------------------------
+//--- web_trim_bufi -----------------------------------------------------------
+//-----------------------------------------------------------------------------
+bool ICACHE_FLASH_ATTR web_trim_bufi(TCP_SERV_CONN *ts_conn, uint8 *pdata, uint32 data_len)
+{
+ if(pdata != NULL && data_len != 0 && ts_conn->sizei > data_len) {
+ rtl_memcpy(ts_conn->pbufi, pdata, data_len); // переместим кусок в начало буфера
+ ts_conn->pbufi = (uint8 *)os_realloc(ts_conn->pbufi, data_len + 1); // mem_trim(ts_conn->pbufi, data_len + 1);
+ if(ts_conn->pbufi != NULL) {
+ ts_conn->sizei = data_len; // размер куска
+ ts_conn->cntri = 0;
+ }
+ else return false; // CurHTTP.httpStatus = 500; // 500 Internal Server Error
+ }
+ else if(ts_conn->pbufi != NULL) {
+ os_free(ts_conn->pbufi);
+ ts_conn->pbufi = NULL;
+ ts_conn->sizei = 0;
+ ts_conn->cntri = 0;
+ };
+ return true;
+}
+/******************************************************************************
+ * web_feee_bufi
+ * освободить приемный буфер
+*******************************************************************************/
+bool ICACHE_FLASH_ATTR web_feee_bufi(TCP_SERV_CONN *ts_conn)
+{
+ if(ts_conn->pbufi != NULL) {
+ os_free(ts_conn->pbufi);
+ ts_conn->pbufi = NULL;
+ ts_conn->sizei = 0;
+ ts_conn->cntri = 0;
+ return true;
+ }
+ return false;
+}
+/******************************************************************************
+ * FunctionName : webserver_recv
+ * Description : Processing the received data from the server
+ * Parameters : arg -- Additional argument to pass to the callback function
+ * pusrdata -- The received data (or NULL when the connection has been closed!)
+ * length -- The length of received data
+ * Returns : none
+ *
+ * For HTTP 1.0, this should normally only happen once (if the request fits in one packet).
+ *
+*******************************************************************************/
+static err_t ICACHE_FLASH_ATTR webserver_received_data(TCP_SERV_CONN *ts_conn)
+{
+#if DEBUGSOO > 1
+ tcpsrv_print_remote_info(ts_conn);
+ os_printf("read: %d ", ts_conn->sizei);
+#endif
+ HTTP_CONN CurHTTP; // Current HTTP connection state
+ WEB_SRV_CONN *web_conn = ReNew_web_conn(ts_conn);
+ if(web_conn == NULL) {
+#if DEBUGSOO > 1
+ os_printf("err mem!\n");
+#endif
+ return ERR_MEM;
+ }
+ if(CheckSCB(SCB_CLOSED | SCB_DISCONNECT | SCB_FCLOSE )) // обрабатывать нечего
+ return ERR_OK;
+ if(!CheckSCB(SCB_WEBSOC)) {
+ web_conn->udata_start = 0;
+ web_conn->udata_stop = 0;
+ }
+ os_memset(&CurHTTP, 0, sizeof(CurHTTP));
+ CurHTTP.httpStatus = 200; // OK
+ CurHTTP.fileType = HTTP_UNKNOWN;
+ // прием и обработка заголовка HHTP
+ if(!CheckSCB(SCB_HEAD_OK)) { // заголовок уже принят и обработан? нет
+ ts_conn->flag.rx_buf = 1; // докачивать буфер
+ tcpsrv_unrecved_win(ts_conn);
+ // разбираем докачан или нет заголовок HTTP, что там принято GET или POST и открываем файл и прием content, если это POST и не прием файла.
+ if(parse_header(&CurHTTP, ts_conn)) { // заголовок полный? нет
+ if(ts_conn->sizei < MAX_HTTP_HEAD_BUF) {
+#if DEBUGSOO > 4
+ os_printf("buf");
+#endif
+#if DEBUGSOO > 1
+ os_printf("...\n");
+#endif
+ return ERR_OK; // будем принимать ещё.
+ };
+ CurHTTP.httpStatus = 413; // 413 Request Entity Too Large // пока так
+ };
+ // разбор заголовка
+#if DEBUGSOO > 1
+#ifdef WEBSOCKET_ENA
+ os_printf("%s f[%s] ", (CheckSCB(SCB_POST))? "POST" : (CheckSCB(SCB_WEBSOC))? "WEBSOC" : "GET", CurHTTP.pFilename);
+#else
+ os_printf("%s f[%s] ", (CheckSCB(SCB_POST))? "POST" : "GET", CurHTTP.pFilename);
+#endif
+#endif
+#if DEBUGSOO > 3
+ os_printf("hcn:%p[%d],wcn:%d ", CurHTTP.pcontent, CurHTTP.content_len, web_conn->content_len);
+#endif
+ if(CurHTTP.httpStatus == 200) { // && CheckSCB(SCB_FOPEN)) { // если файл открыт и всё OK
+ if(CurHTTP.cookie_len != 0) web_parse_cookie(&CurHTTP, ts_conn);
+ web_parse_uri_vars(&CurHTTP, ts_conn);
+ if(CurHTTP.pcontent != NULL) {
+ if(CheckSCB(SCB_RXDATA)) {
+ if(web_conn->content_len) { // с заголовком приняли кусок данных файла?
+#if DEBUGSOO > 3
+ os_printf("trim:%u[%u] ", web_conn->content_len, CurHTTP.content_len);
+#endif
+ if(!web_trim_bufi(ts_conn, CurHTTP.pcontent, CurHTTP.content_len)) {
+#if DEBUGSOO > 1
+ os_printf("trim error!\n");
+#endif
+ CurHTTP.httpStatus = 500;
+ };
+ };
+ }
+ else {
+ if(CurHTTP.content_len != 0) web_parse_content(&CurHTTP, ts_conn);
+ };
+ };
+ };
+ SetSCB(SCB_HEAD_OK); // заголовок принят и обработан
+ };
+#if DEBUGSOO > 3
+ os_printf("tst_rx: %u, %u, %u ", CurHTTP.httpStatus, (CheckSCB(SCB_RXDATA) != 0), web_conn->content_len );
+#endif
+ // проверка на прием данных (content)
+ if(CurHTTP.httpStatus == 200 && CheckSCB(SCB_RXDATA) && (web_conn->content_len) && web_rx_buf(&CurHTTP, ts_conn)) {
+#if DEBUGSOO > 1
+ os_printf("...\n");
+#endif
+ return ERR_OK; // докачивать content
+ };
+#ifdef WEBSOCKET_ENA
+ if(CheckSCB(SCB_WEBSOC) && CurHTTP.httpStatus == 200 && (!CheckSCB(SCB_REDIR))) {
+ if(!CheckSCB(SCB_WSDATA)) {
+ // создание и вывод заголовка ответа websock
+ ClrSCB(SCB_RXDATA);
+ Close_web_conn(ts_conn); // закрыть все файлы
+ web_print_headers(&CurHTTP, ts_conn);
+ if(CheckSCB(SCB_DISCONNECT)) {
+ ts_conn->flag.rx_null = 1; // всё - больше не принимаем!
+ ts_conn->flag.rx_buf = 0; // не докачивать буфер
+ if(web_feee_bufi(ts_conn)) tcpsrv_unrecved_win(ts_conn); // уничтожим буфер
+ }
+ else {
+ SetSCB(SCB_WSDATA);
+ ts_conn->flag.rx_buf = 1; // указать, что всегда в режиме докачивать
+ tcpsrv_unrecved_win(ts_conn);
+ tcp_output(ts_conn->pcb);
+
+ if(web_feee_bufi(ts_conn)) tcpsrv_unrecved_win(ts_conn); // уничтожим буфер
+/*
+ if(ts_conn->pbufi != NULL && ts_conn->sizei != 0) { // что-то ещё есть в буфере?
+#if DEBUGSOO > 1
+ os_printf("ws_rx[%u]? ", ts_conn->sizei);
+#endif
+ websock_rx_data(ts_conn);
+ }
+*/
+ }
+ }
+ else {
+ websock_rx_data(ts_conn);
+ }
+ }
+ else
+#endif
+ {
+ ts_conn->flag.rx_null = 1; // всё - больше не принимаем!
+ ts_conn->flag.rx_buf = 0; // не докачивать буфер
+ if(web_feee_bufi(ts_conn)) tcpsrv_unrecved_win(ts_conn); // уничтожим буфер
+ if(tcp_sndbuf(ts_conn->pcb) >= HTTP_SEND_SIZE) { // возможна втавка ответа?
+ // создание и вывод заголовка ответа.
+ web_print_headers(&CurHTTP, ts_conn);
+ // начало предачи файла, если есть
+ if((!CheckSCB(SCB_CLOSED | SCB_DISCONNECT | SCB_FCLOSE))&&CheckSCB(SCB_FOPEN)) webserver_send_fdata(ts_conn);
+ }
+ else {
+#if DEBUGSOO > 1
+ os_printf("sndbuf=%u! ", tcp_sndbuf(ts_conn->pcb));
+#endif
+ SetSCB(SCB_FCLOSE | SCB_DISCONNECT);
+ };
+ }
+ if(CheckSCB(SCB_FCLOSE)) {
+ tcp_output(ts_conn->pcb);
+ Close_web_conn(ts_conn);
+ SetSCB(SCB_DISCONNECT);
+ }
+ if(CheckSCB(SCB_DISCONNECT)) web_int_disconnect(ts_conn);
+#if DEBUGSOO > 1
+ else os_printf("...\n");
+#endif
+ return ERR_OK;
+}
+/******************************************************************************
+ * web_int_disconnect
+*******************************************************************************/
+static void ICACHE_FLASH_ATTR web_int_disconnect(TCP_SERV_CONN *ts_conn)
+{
+#if DEBUGSOO > 1
+ os_printf("dis\n");
+#endif
+ WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
+ ts_conn->flag.tx_null = 1;
+ ts_conn->flag.rx_null = 1;
+ tcpsrv_unrecved_win(ts_conn);
+ if(ts_conn->flag.pcb_time_wait_free) tcpsrv_disconnect(ts_conn);
+ SetSCB(SCB_CLOSED);
+}
+/******************************************************************************
+ * FunctionName : webserver_sent_cb
+ * Description : Sent callback function to call for this espconn when data
+ * is successfully sent
+ * Parameters : arg -- Additional argument to pass to the callback function
+ * Returns : none
+*******************************************************************************/
+static err_t ICACHE_FLASH_ATTR webserver_sent_callback(TCP_SERV_CONN *ts_conn)
+{
+#if DEBUGSOO > 1
+ tcpsrv_print_remote_info(ts_conn);
+#endif
+ WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
+ if(web_conn == NULL) return ERR_ARG;
+ if(CheckSCB(SCB_CLOSED) == 0) { // No SCB_CLOSED
+ if(!CheckSCB(SCB_DISCONNECT)) {
+#ifdef WEBSOCKET_ENA
+ if(CheckSCB(SCB_WSDATA)) {
+ websock_rx_data(ts_conn);
+ }
+ else
+#endif
+ if((!CheckSCB(SCB_FCLOSE))&&CheckSCB(SCB_FOPEN)) webserver_send_fdata(ts_conn);
+ }
+ if(CheckSCB(SCB_FCLOSE)) {
+ Close_web_conn(ts_conn);
+ SetSCB(SCB_DISCONNECT);
+ }
+ if(CheckSCB(SCB_DISCONNECT)) web_int_disconnect(ts_conn);
+ #if DEBUGSOO > 1
+ else os_printf("...\n");
+ #endif
+ }
+ else { // SCB_CLOSED
+#if DEBUGSOO > 1
+ os_printf("#%04x ?\n", web_conn->webflag);
+#endif
+ ts_conn->flag.tx_null = 1;
+ ts_conn->flag.rx_null = 1;
+ };
+ return ERR_OK;
+}
+/******************************************************************************
+ * FunctionName : webserver_disconnect
+ * Description : calback disconnect
+ * Parameters : arg -- Additional argument to pass to the callback function
+ * Returns : none
+*******************************************************************************/
+static void ICACHE_FLASH_ATTR webserver_disconnect(TCP_SERV_CONN *ts_conn)
+{
+#if DEBUGSOO > 1
+ tcpsrv_disconnect_calback_default(ts_conn);
+#endif
+ WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
+ if(web_conn == NULL) return;
+ Close_web_conn(ts_conn);
+ if(CheckSCB(SCB_SYSSAVE)) {
+ ClrSCB(SCB_SYSSAVE);
+ sys_write_cfg();
+ };
+}
+
+/******************************************************************************
+******************************************************************************/
+BaseType_t webserver_qfn(web_ex_func_cb fnc, void * param, uint16 pause_ms) {
+ WEB_SRV_QFNK qfn;
+ qfn.fnc = fnc;
+ qfn.param = param;
+ qfn.pause_ms = pause_ms;
+ return xQueueSendToBack(xQueueWebSrv, &qfn, 0);
+}
+/******************************************************************************
+ * todo: временная затычка, необходимо переделать...
+******************************************************************************/
+void qfnk_task(void)
+{
+ WEB_SRV_QFNK qfn;
+ WEB_SRV_QFNK qfnt;
+ TickType_t timetick;
+ qfnt.fnc = NULL;
+ qfnt.pause_ms = 0;
+ while(1) {
+ if(xQueueReceive(xQueueWebSrv, &qfn, 5) == pdPASS) { // portMAX_DELAY
+ if(qfn.fnc) {
+#if DEBUGSOO > 2
+ os_printf("qfn: %p(%p),%d\n", qfn.fnc, qfn.param, qfn.pause_ms);
+#endif
+ if(qfn.pause_ms) {
+ timetick = xTaskGetTickCount();
+ qfnt = qfn;
+ }
+ else qfn.fnc((uint32) qfn.param);
+ }
+ }
+ else if(qfnt.fnc) {
+ if(xTaskGetTickCount() - timetick > qfnt.pause_ms) {
+#if DEBUGSOO > 3
+ os_printf("qfnt: %p(%p),%d\n", qfnt.fnc, qfnt.param, qfnt.pause_ms);
+#endif
+ qfnt.fnc((uint32) qfnt.param);
+ qfnt.fnc = NULL;
+ }
+ }
+ }
+}
+/******************************************************************************
+ * FunctionName : webserver_init
+ * Description : Открытие сервера
+ * Parameters : arg -- port N
+ * Returns : none
+*******************************************************************************/
+err_t ICACHE_FLASH_ATTR webserver_init(uint16 portn)
+{
+// WEBFSInit(); // файловая система
+ err_t err = ERR_MEM;
+ xQueueWebSrv = xQueueCreate(5, sizeof( WEB_SRV_QFNK )); // Create a queue...
+ if(xQueueWebSrv) {
+ if(xTaskCreate(qfnk_task, "web_qfn", 1024, NULL, tskIDLE_PRIORITY + 1 + PRIORITIE_OFFSET, NULL) == pdPASS)
+ {
+ TCP_SERV_CFG *p = tcpsrv_init(portn);
+ if (p != NULL) {
+ // изменим конфиг на наше усмотрение:
+ if(syscfg.cfg.b.web_time_wait_delete) p->flag.pcb_time_wait_free = 1; // пусть убивает, для теста и проксей
+ p->max_conn = 99; // сработает по heap_size
+#if DEBUGSOO > 3
+ os_printf("Max connection %d, time waits %d & %d, min heap size %d\n",
+ p->max_conn, p->time_wait_rec, p->time_wait_cls, p->min_heap);
+#endif
+ p->time_wait_rec = syscfg.web_twrec; // if =0 -> вечное ожидание
+ p->time_wait_cls = syscfg.web_twcls; // if =0 -> вечное ожидание
+ // слинкуем с желаемыми процедурами:
+ p->func_discon_cb = webserver_disconnect;
+ // p->func_listen = webserver_listen; // не требуется
+ p->func_sent_cb = webserver_sent_callback;
+ p->func_recv = webserver_received_data;
+ err = tcpsrv_start(p);
+ if (err != ERR_OK) {
+ tcpsrv_close(p);
+ p = NULL;
+ }
+ else {
+#if DEBUGSOO > 1
+ os_printf("WEB: init port %u\n", portn);
+#endif
+ }
+
+ }
+// else err = ERR_MEM;
+ }
+// else err = ERR_MEM;
+ }
+// else err = ERR_MEM;
+ return err;
+}
+/******************************************************************************
+ * FunctionName : webserver_close
+ * Description : закрытие сервера
+ * Parameters : arg -- port N
+ * Returns : none
+*******************************************************************************/
+err_t ICACHE_FLASH_ATTR webserver_close(uint16 portn)
+{
+ err_t err = ERR_ARG;
+ if(portn != 0) err = tcpsrv_close(tcpsrv_server_port2pcfg(portn));
+#if DEBUGSOO > 1
+ if(err == ERR_OK) os_printf("WEB: close\n");
+#endif
+ if(xQueueWebSrv) {
+ WEB_SRV_QFNK qfn;
+ qfn.fnc = (web_ex_func_cb) vTaskDelete;
+ qfn.param = NULL;
+ qfn.pause_ms = 0;
+ if(xQueueSendToBack(xQueueWebSrv, &qfn, 1000) == pdPASS) {
+ while(uxQueueMessagesWaiting(xQueueWebSrv)) {
+ vTaskDelay(10);
+ };
+ }
+ xQueueWebSrv = NULL;
+ };
+ return err;
+}
+/******************************************************************************
+ * FunctionName : webserver_reinit
+ * Description : закрытие сервера и открытие нового
+ * Parameters : arg -- port N открытого порта
+ * Returns : none
+*******************************************************************************/
+err_t ICACHE_FLASH_ATTR webserver_reinit(uint16 portn)
+{
+ err_t err = ERR_OK;
+// if(portn == syscfg.web_port) return err;
+ if(portn) err = tcpsrv_close(tcpsrv_server_port2pcfg(portn)); // закрыть старый порт
+ if(syscfg.web_port) err = webserver_init(syscfg.web_port); // открыть новый
+ return err;
+}
+
+#endif // USE_WEB
diff --git a/RTLGDB/Project/web/web_srv.h b/RTLGDB/Project/web/web_srv.h
new file mode 100644
index 0000000..722ea49
--- /dev/null
+++ b/RTLGDB/Project/web/web_srv.h
@@ -0,0 +1,210 @@
+/*
+ * File: web_srv.h
+ * Description: The web server configration.
+ * Small WEB server ESP8266EX
+ * Author: PV`
+ */
+
+#ifndef _INCLUDE_WEB_SRV_H_
+#define _INCLUDE_WEB_SRV_H_
+
+#include "tcpsrv/tcp_srv_conn.h"
+#ifdef WEBSOCKET_ENA
+#include "websock.h"
+#endif
+
+#define WEB_SVERSION "0.2.0"
+#define DEFAULT_WEB_PORT USE_WEB // 80
+#define USE_WEB_AUTH_LEVEL 0 // 1
+
+/****************************************************************************
+ ***************************************************************************/
+
+typedef enum
+{
+ WEB_AUTH_NONE = 0,
+ WEB_AUTH_LEVEL_USER,
+ WEB_AUTH_LEVEL_USER1,
+ WEB_AUTH_LEVEL_WEBFS,
+ WEB_AUTH_LEVEL_OTA,
+ WEB_AUTH_LEVEL_SUPERVISOR
+} WEB_AUTH_LEVEL_TYPE;
+
+// File type definitions
+typedef enum
+{
+ HTTP_TXT = 0, // File is a text document
+ HTTP_HTML, // File is HTML (extension .htm)
+ HTTP_CGI, // File is HTML (extension .cgi)
+ HTTP_XML, // File is XML (extension .xml)
+ HTTP_CSS, // File is stylesheet (extension .css)
+ HTTP_ICO, // File is ICO vnd.microsoft.icon
+ HTTP_GIF, // File is GIF image (extension .gif)
+ HTTP_PNG, // File is PNG image (extension .png)
+ HTTP_JPG, // File is JPG image (extension .jpg)
+ HTTP_SVG, // File is SVG image (extension .svg)
+ HTTP_JAVA, // File is java (extension .js)
+ HTTP_SWF, // File is ShockWave-Flash (extension .swf)
+ HTTP_WAV, // File is audio (extension .wav)
+ HTTP_PDF, // File is PDF (extension .pdf)
+ HTTP_ZIP, // File is ZIP (extension .zip)
+ HTTP_BIN, // File is BIN (extension .bin)
+ HTTP_UNKNOWN // File type is unknown
+} HTTP_FILE_TYPE;
+
+
+// extended state data for each connection
+#define FileNameSize 64
+#define VarNameSize 64
+#define CmdNameSize 32
+
+typedef struct
+{
+ uint16 httpStatus; // Request method/status
+ uint16 uri_len;
+ uint16 head_len;
+ uint16 cookie_len;
+ uint8 pFilename[FileNameSize];
+ uint8 *puri; // указатель на строку с переменными запроса к файлу
+ uint8 *phead; // HTTP Headers
+ uint8 *pcookie; // cookie
+ uint8 *pcontent; // content
+ uint32 content_len; //
+ uint8 httpver; // версия HTTP клиента в BCD (0x00 = неизвестен; 0x09 = HTTP/0.9; 0x10 = HTTP/1.0; 0x11 = HTTP/1.1)
+ uint8 fileType; // File type to return with Content-Type
+} HTTP_CONN;
+
+
+typedef void (* web_func_cb)(TCP_SERV_CONN *ts_conn);
+typedef uint32 (* web_ex_func_cb)(uint32 flg); // внешняя или отложенная функция
+
+typedef struct
+{
+ web_ex_func_cb fnc;
+ void * param;
+ uint16 pause_ms;
+} WEB_SRV_QFNK;
+
+typedef struct
+{
+ uint32 webflag; // флаги для http/web сервера
+ uint8 bffiles[4]; // четыре Files pointers для оработки вложенных файлов include
+ uint32 udata_start; // udata "start=0x..."
+ uint32 udata_stop; // udata "stop=0x..."
+ uint8 *msgbuf; // указатель на текущий буфер вывода
+ uint16 msgbuflen; // кол-во занятых байт в буфере msgbuf
+ uint16 msgbufsize; // размер буфера
+ web_func_cb func_web_cb; // calback функция у httpd для обработки приема/передачи кусками
+ uint32 content_len; // размер файла для передачи (GET/POST) или приема, если принимается внешний файл (POST + SCB_RXDATA)
+#ifdef WEBSOCKET_ENA
+ WS_FRSTAT ws; // параметры websoc
+#endif
+#if USE_WEB_AUTH_LEVEL
+ uint8 auth_level; // Уровень авторизации пользователя по паролю WEB_AUTH_LEVEL_TYPE
+ uint8 auth_realm; // Требуемый уровень авторизации (минимальный уровень) WEB_AUTH_LEVEL_TYPE
+#endif
+ uint8 fileType; // File type to return with Content-Type (if SCB_FCALBACK)
+} WEB_SRV_CONN;
+
+typedef enum
+{
+ WEBFS_MAX_HANDLE = 251,
+ WEBFS_NODISK_HANDLE,
+ WEBFS_WEBCGI_HANDLE,
+ WEBFS_UPLOAD_HANDLE
+} WEBFS_NUM_HANDLE;
+
+// webflag:
+
+#define SCB_CLOSED 0x000001 // соединение закрыто
+#define SCB_DISCONNECT 0x000002 // выход на DISCONNECT
+#define SCB_FCLOSE 0x000004 // закрыть файлы
+#define SCB_FOPEN 0x000008 // файл(ы) открыт(ы)
+#define SCB_FCALBACK 0x000010 // file use ~calback~
+#define SCB_FGZIP 0x000020 // файл GZIP
+#define SCB_CHUNKED 0x000040 // передача шинковкой
+#define SCB_RETRYCB 0x000080 // вызвать повтор CalBack
+#define SCB_POST 0x000100 // POST
+#define SCB_GET 0x000200 // GET
+#define SCB_AUTH 0x000400 // необходима авторизация
+#define SCB_FINDCB 0x000800 // используется парсингом ~calback~
+#define SCB_RXDATA 0x001000 // прием данных (файла)
+#define SCB_HEAD_OK 0x002000 // заголовок HTTP принят и обработан
+#define SCB_BNDR 0x004000 // прилеплен Content-Type: multipart/form-data; boundary="..."
+#define SCB_REDIR 0x008000 // Redirect 302
+#define SCB_WEBSOC 0x010000 // WebSocket
+#define SCB_WSDATA 0x020000 // WebSocket data
+#define SCB_SYSSAVE 0x040000 // по закрытию соединения вызвать sys_write_cfg()
+
+
+#define SCB_OPEN 0
+
+#define SetSCB(a) web_conn->webflag |= a
+#define FreeSCB() web_conn->webflag = SCB_FREE
+#define SetNextFunSCB(a) web_conn->func_web_cb = a
+#define ClrSCB(a) web_conn->webflag &= ~(a)
+#define CheckSCB(a) (web_conn->webflag & (a))
+
+#define FreeSCB() web_conn->webflag = SCB_FREE
+#define OpenSCB() web_conn->webflag = SCB_OPEN
+
+#define MAXLENBOUNDARY 64
+typedef struct s_http_upload
+{
+ uint16 status;
+ uint16 sizeboundary;
+ uint8 boundary[MAXLENBOUNDARY+1];
+ uint8 name[VarNameSize];
+ uint8 filename[VarNameSize];
+#ifdef USE_OVERLAY
+ uint32 segs; // кол-во сегментов оверлея // пока в web_conn->web_disc_par
+ uint32 start; // адрес запуска оверлея
+#endif
+ uint32 fsize;
+ uint32 faddr;
+ uint8 *pbndr;
+ uint8 *pnext;
+} HTTP_UPLOAD;
+
+typedef struct s_http_response
+{
+ uint32 status;
+ uint32 flag;
+ const char * headers;
+ const char * default_content;
+} HTTP_RESPONSE;
+
+// HTTP_RESPONSE.flags:
+#define HTTP_RESP_FLG_END 0x8000
+#define HTTP_RESP_FLG_NONE 0x0000
+#define HTTP_RESP_FLG_FINDFILE 0x0001
+#define HTTP_RESP_FLG_REDIRECT 0x0002
+
+#define tcp_put(a) web_conn->msgbuf[web_conn->msgbuflen++] = a
+#define tcp_htmlstrcpy(str, len) web_conn->msgbuflen += htmlcode(&web_conn->msgbuf[web_conn->msgbuflen], str, web_conn->msgbufsize - web_conn->msgbuflen - 1, len)
+//#define tcp_urlstrcpy(str, len) web_conn->msgbuflen += urlencode(&web_conn->msgbuf[web_conn->msgbuflen], str, web_conn->msgbufsize - web_conn->msgbuflen - 1, len)
+#define tcp_puts(...) web_conn->msgbuflen += rtl_sprintf((char *)&web_conn->msgbuf[web_conn->msgbuflen], __VA_ARGS__)
+#define tcp_puts_fd(...) web_conn->msgbuflen += rtl_sprintf((char *)&web_conn->msgbuf[web_conn->msgbuflen], __VA_ARGS__)
+/*
+#define tcp_puts_fd(fmt, ...) do { \
+ static const char flash_str[] ICACHE_RODATA_ATTR = fmt; \
+ web_conn->msgbuflen += rtl_sprintf((char *)&web_conn->msgbuf[web_conn->msgbuflen], (char *)flash_str, ##__VA_ARGS__); \
+ } while(0)
+*/
+//#define tcp_strcpy(a) web_conn->msgbuflen += ets_strlen((char *)ets_strcpy((char *)&web_conn->msgbuf[web_conn->msgbuflen], (char *)a))
+#define tcp_strcpy(a) web_conn->msgbuflen += rom_xstrcpy((char *)&web_conn->msgbuf[web_conn->msgbuflen], (const char *)a)
+#define tcp_strcpy_fd(a) web_conn->msgbuflen += rom_xstrcpy((char *)&web_conn->msgbuf[web_conn->msgbuflen], (const char *)a)
+/*
+#define tcp_strcpy_fd(fmt) do { \
+ static const char flash_str[] ICACHE_RODATA_ATTR = fmt; \
+ web_conn->msgbuflen += rom_xstrcpy((char *)&web_conn->msgbuf[web_conn->msgbuflen], (char *)flash_str); \
+ } while(0)
+*/
+uint32 ahextoul(uint8 *s);
+err_t webserver_init(uint16 portn);
+err_t webserver_close(uint16 portn);
+err_t webserver_reinit(uint16 portn);
+
+BaseType_t webserver_qfn(web_ex_func_cb fnc, void * param, uint16 pause_ms); // вызов функции из task с low priority
+
+#endif /* _INCLUDE_WEB_SRV_H_ */
diff --git a/RTLGDB/Project/web/web_srv_int.h b/RTLGDB/Project/web/web_srv_int.h
new file mode 100644
index 0000000..2b28919
--- /dev/null
+++ b/RTLGDB/Project/web/web_srv_int.h
@@ -0,0 +1,48 @@
+/*
+ * File: web_srv_int.h
+ * Description: The web server configration.
+ * Small WEB server ESP8266EX
+ *
+ * Author: PV` 12/2014
+ */
+
+#ifndef _INCLUDE_WEB_SRV_INT_H_
+#define _INCLUDE_WEB_SRV_INT_H_
+
+#include "web_srv.h"
+
+#define WEB_NAME_VERSION "PVs/0.2"
+
+// lifetime (sec) of static responses as string 60*60*24*14=1209600"
+#define FILE_CACHE_MAX_AGE_SEC 3600 // время для кеша файлов, ставить 0 пока тест!
+
+#define MAX_HTTP_HEAD_BUF TCP_SRV_SERVER_MAX_RXBUF // максимальный размер HTTP запроса (GET)
+
+#define RESCHKS_SEND_SIZE 16
+#define RESCHKE_SEND_SIZE 8
+#define RESCHK_SEND_SIZE (RESCHKS_SEND_SIZE + RESCHKE_SEND_SIZE)
+
+#define MIN_SEND_SIZE (256 + RESCHK_SEND_SIZE) // минимальный размер буфера для передачи файла
+#define MAX_SEND_SIZE ((TCP_SND_BUF) + RESCHK_SEND_SIZE) // ((TCP_MSS*4) + RESCHK_SEND_SIZE) // максимальный размер буфера для передачи 4*MSS = 5840 (MSS=1460)
+
+#define HTTP_SEND_SIZE 384 // минимальный размер буфера для передачи заголовка HTTP
+#define SCB_SEND_SIZE 128 // минимальный резерв в буфере для callback
+
+#define webfile bffiles[0] // File pointer for main file
+
+//-----------------------------------------------------------------------------
+
+void web_int_vars(TCP_SERV_CONN *ts_conn, uint8 *pcmd, uint8 *pvar);
+void web_int_cookie(HTTP_CONN *CurHTTP, TCP_SERV_CONN *ts_conn);
+void web_int_callback(TCP_SERV_CONN *ts_conn, uint8 *cstr);
+
+void web_hexdump(TCP_SERV_CONN *ts_conn);
+bool web_inc_fopen(TCP_SERV_CONN *ts_conn, uint8 *cFile);
+bool web_inc_fclose(WEB_SRV_CONN *web_conn);
+
+bool web_trim_bufi(TCP_SERV_CONN *ts_conn, uint8 *pdata, uint32 data_len);
+bool web_feee_bufi(TCP_SERV_CONN *ts_conn);
+//uint8 * head_find_ctr(HTTP_CONN *CurHTTP, const uint8 * c, int clen, int dlen);
+uint8 UserAuthorization(uint8 *pbuf, size_t declen);
+
+#endif /* _INCLUDE_WEB_SRV_INT_H_ */
diff --git a/RTLGDB/Project/web/web_utils.c b/RTLGDB/Project/web/web_utils.c
new file mode 100644
index 0000000..a7700f7
--- /dev/null
+++ b/RTLGDB/Project/web/web_utils.c
@@ -0,0 +1,680 @@
+/*
+ * web_utils.c
+ *
+ * Created on: 25 дек. 2014 г.
+ * Author: PV`
+ */
+#include "user_config.h"
+#include "autoconf.h"
+#include "FreeRTOS.h"
+#include "task.h"
+#include "diag.h"
+//#include "bios.h"
+//#include "sdk/add_func.h"
+//#include "ets_sys.h"
+//#include "os_type.h"
+//#include "osapi.h"
+//#include "user_interface.h"
+#include "web_utils.h"
+#include "esp_comp.h"
+
+#define mMIN(a, b) ((a= '0' && *s <= '9')
+ n = 10*n - (*s++ - '0');
+ return neg ? n : -n;
+}
+
+/******************************************************************************
+ * get_seg_id()
+*******************************************************************************/
+const char * const txt_tab_seg[] = {
+ "ROM" // 0
+ "SRAM", // 1
+ "TCM", // 2
+ "FLASH", // 3 // -> flash On
+ "SDRAM", // 4 // -> Test ChipID or HAL_PERI_ON_WRITE32(REG_SOC_FUNC_EN, HAL_PERI_ON_READ32(REG_SOC_FUNC_EN) | BIT(21)); // Flag SDRAM Off
+ "SOC", // 5 // protected !
+ "CPU", // 6 // protected !
+ "UNK", // 7
+ };
+
+const uint32 tab_seg_def[] = {
+ 0x00000000, 0x00050000,
+ 0x10000000, 0x10070000,
+ 0x1fff0000, 0x20000000,
+ 0x98000000, 0xA0000000,
+ 0x30000000, 0x30200000,
+ 0x40000000, 0x40800000,
+ 0xE0000000, 0xE0010000,
+ 0x00000000, 0xFFFFFFFF
+};
+
+SEG_ID get_seg_id(uint32 addr, int32 size) {
+ SEG_ID ret = SEG_ID_ERR;
+ uint32 * ptr = (uint32 *) &tab_seg_def;
+ if (size > 0) {
+ do {
+ ret++;
+ if (addr >= ptr[0] && addr + size <= ptr[1]) {
+ return ret;
+ };
+ ptr += 2;
+ } while (ret < SEG_ID_MAX);
+ };
+ return 0;
+}
+/******************************************************************************
+ * copy_align4
+ * копирует данные из области кеширования flash и т.д.
+*******************************************************************************/
+void ICACHE_FLASH_ATTR copy_align4(void *ptrd, void *ptrs, uint32 len)
+{
+ union {
+ uint8 uc[4];
+ uint32 ud;
+ }tmp;
+ uint8 *pd = ptrd;
+ uint32 *p = (uint32 *)((uint32)ptrs & (~3));
+ uint32 xlen = ((uint32)ptrs) & 3;
+ if(xlen) {
+ if(((uint32)p >= 0x10000000)&&((uint32)p < 0x9A002000)) tmp.ud = *p++;
+ else {
+ tmp.ud = 0;
+ p++;
+ }
+ while (len) {
+ *pd++ = tmp.uc[xlen++];
+ len--;
+ if(xlen >= 4) break;
+ }
+ }
+ xlen = len >> 2;
+ while(xlen) {
+ if(((uint32)p >= 0x10000000)&&((uint32)p < 0x9A002000)) tmp.ud = *p++;
+ else {
+ tmp.ud = 0;
+ p++;
+ }
+ *pd++ = tmp.uc[0];
+ *pd++ = tmp.uc[1];
+ *pd++ = tmp.uc[2];
+ *pd++ = tmp.uc[3];
+ xlen--;
+ }
+ len &= 3;
+ if(len) {
+ if(((uint32)p >= 0x10000000)&&((uint32)p < 0x9A002000)) tmp.ud = *p;
+ else tmp.ud = 0;
+ uint8 * ptmp = tmp.uc;
+ while (len--) *pd++ = *ptmp++;
+ }
+}
+/******************************************************************************
+ * FunctionName : hextoul
+*******************************************************************************/
+// bool conv_str_hex(uint32 * dest, uint8 *s);
+uint32 ICACHE_FLASH_ATTR hextoul(uint8 *s)
+{
+/*
+ uint32 val;
+ if(!conv_str_hex(&val, s)) return 0;
+ return val;
+*/
+ uint32 val = 0;
+ while (*s)
+ {
+ if (*s >= '0' && *s <= '9')
+ {
+ val <<= 4;
+ val |= *s - '0';
+ }
+ else if (*s >= 'A' && *s <= 'F')
+ {
+ val <<= 4;
+ val |= *s - 'A' + 10;
+ }
+ else if (*s >= 'a' && *s <= 'f')
+ {
+ val <<= 4;
+ val |= *s - 'a' + 10;
+ }
+ else break;
+ s++;
+ };
+ return val;
+}
+/******************************************************************************
+ * FunctionName : ahextoul
+*******************************************************************************/
+// bool convert_para_str(uint32 * dest, uint8 *s);
+uint32 ICACHE_FLASH_ATTR ahextoul(uint8 *s)
+{
+/*
+ uint32 ret;
+ if(!convert_para_str(&ret, s)) return 0;
+ return ret;
+*/
+ if((s[0]=='0') && ((s[1] | 0x20) =='x')) return hextoul(s+2);
+ return rom_atoi(s);
+}
+/******************************************************************************
+ * FunctionName : cmpcpystr
+ * Description : выбирает слово из строки текста с заданными начальным символом
+ * и конечным терминатором. Терминатор и стартовый символ не копирует, если заданы.
+ * Parameters : При задании начального символа = '\0' берется любой символ (>' ').
+ Копирует до символа <' ' или терминатора.
+ Задается ограничение размера буфера для копируемого слова (с дописыванием в буфер '\0'!).
+ * Returns : Зависит от значения терминатора, указывает на терминатор в строке,
+ если терминатор найден.
+ Если NULL, то начальный или конечный терминатор не найден.
+*******************************************************************************/
+uint8 * ICACHE_FLASH_ATTR cmpcpystr(uint8 *pbuf, uint8 *pstr, uint8 a, uint8 b, uint16 len)
+{
+ if(len == 0) pbuf = NULL;
+ if(pstr == NULL) {
+ if(pbuf != NULL) *pbuf='\0';
+ return NULL;
+ };
+ uint8 c;
+ do {
+ c = *pstr;
+ if(c < ' ') { // строка кончилась
+ if(pbuf != NULL) *pbuf='\0';
+ return NULL; // id не найден
+ };
+ if((a == '\0')&&(c > ' ')) break; // не задан -> любой символ
+ pstr++;
+ if(c == a) break; // нашли стартовый символ (некопируемый в буфер)
+ }while(1);
+ if(pbuf != NULL) {
+ while(len--) {
+ c = *pstr;
+ if(c == b) { // нашли терминирующий символ (некопируемый в буфер)
+ *pbuf='\0';
+ return pstr; // конечный терминатор найден
+ };
+// if(c <= ' ') { // строка кончилась или пробел
+ if(c < ' ') { // строка кончилась или пробел
+ *pbuf='\0';
+ return NULL; // конечный терминатор не найден
+ };
+ pstr++;
+ *pbuf++ = c;
+ };
+ *--pbuf='\0'; // закрыть буфер
+ };
+ do {
+ c = *pstr;
+ if(c == b) return pstr; // нашли терминирующий символ
+// if(c <= ' ') return NULL; // строка кончилась
+ if(c < ' ') return NULL; // строка кончилась
+ pstr++;
+ }while(1);
+}
+/******************************************************************************
+ * FunctionName : str_array
+ * Набирает из строки s массив слов в buf в кол-ве до max_buf
+ * возврат - кол-во переменных в строке
+ * Разделитель переменных в строке ','
+ * Если нет переменной, то пропускает изменение в buf
+ * Примеры:
+ * Строка "1,2,3,4" -> buf = 0x01 0x02 0x03 0x04
+ * Строка "1,,3," -> buf = 0x01 (не изменено) 0x03 (не изменено)
+*******************************************************************************/
+uint32 ICACHE_FLASH_ATTR str_array(uint8 *s, uint32 *buf, uint32 max_buf)
+{
+ uint32 ret = 0;
+ uint8 *sval = NULL;
+ while(max_buf > ret) {
+ if(sval == NULL) {
+ if (*s == '-' && s[1] >= '0' && s[1] <= '9') {
+ sval = s;
+ s++;
+ }
+ else if (*s >= '0' && *s <= '9') sval = s;
+ }
+ if(*s == ',' || *s <= ')') {
+ if(sval != NULL) {
+ *buf = ahextoul(sval);
+ sval = NULL;
+ }
+ buf++;
+ ret++;
+ if(*s < ')') return ret;
+ }
+ s++;
+ }
+ return ret;
+}
+uint32 ICACHE_FLASH_ATTR str_array_w(uint8 *s, uint16 *buf, uint32 max_buf)
+{
+ uint32 ret = 0;
+ uint8 *sval = NULL;
+ while(max_buf > ret) {
+ if(sval == NULL) {
+ if (*s == '-' && s[1] >= '0' && s[1] <= '9') {
+ sval = s;
+ s++;
+ }
+ else if (*s >= '0' && *s <= '9') sval = s;
+ }
+ if(*s == ',' || *s <= ')') {
+ if(sval != NULL) {
+ *buf = ahextoul(sval);
+ sval = NULL;
+ }
+ buf++;
+ ret++;
+ if(*s < ')') return ret;
+ }
+ s++;
+ }
+ return ret;
+}
+uint32 ICACHE_FLASH_ATTR str_array_b(uint8 *s, uint8 *buf, uint32 max_buf)
+{
+ uint32 ret = 0;
+ uint8 *sval = NULL;
+ while(max_buf > ret) {
+ if(sval == NULL) {
+ if (*s == '-' && s[1] >= '0' && s[1] <= '9') {
+ sval = s;
+ s++;
+ }
+ else if (*s >= '0' && *s <= '9') sval = s;
+ }
+ if(*s == ',' || *s == '.' || *s <= ')') {
+ if(sval != NULL) {
+ *buf = ahextoul(sval);
+ sval = NULL;
+ }
+ buf++;
+ ret++;
+ if(*s < ')') return ret;
+ }
+ s++;
+ }
+ return ret;
+}
+/******************************************************************************
+ * FunctionName : strtmac
+*******************************************************************************/
+void ICACHE_FLASH_ATTR strtomac(uint8 *s, uint8 *macaddr)
+{
+ uint8 pbuf[4];
+ s = cmpcpystr(pbuf, s, 0, ':', 3);
+ *macaddr++ = hextoul(pbuf);
+ int i = 4;
+ while(i--) {
+ s = cmpcpystr(pbuf, s, ':', ':', 3);
+ *macaddr++ = hextoul(pbuf);
+ }
+ s = cmpcpystr(pbuf, s, ':', ' ', 3);
+ *macaddr++ = hextoul(pbuf);
+}
+/******************************************************************************
+ * FunctionName : urldecode
+*******************************************************************************/
+int ICACHE_FLASH_ATTR urldecode(uint8 *d, uint8 *s, uint16 lend, uint16 lens)
+{
+ uint16 ret = 0;
+ if(s != NULL) while ((lens--) && (lend--) && (*s > ' ')) {
+ if ((*s == '%')&&(lens > 1)) {
+ s++;
+ int i = 2;
+ uint8 val = 0;
+ while(i--) {
+ if (*s >= '0' && *s <= '9') {
+ val <<= 4;
+ val |= *s - '0';
+ } else if (*s >= 'A' && *s <= 'F') {
+ val <<= 4;
+ val |= *s - 'A' + 10;
+ } else if (*s >= 'a' && *s <= 'f') {
+ val <<= 4;
+ val |= *s - 'a' + 10;
+ } else
+ break;
+ s++;
+ lens--;
+ };
+ s--;
+ *d++ = val;
+ } else if (*s == '+')
+ *d++ = ' ';
+ else
+ *d++ = *s;
+ ret++;
+ s++;
+ }
+ *d = '\0';
+ return ret;
+}
+/******************************************************************************
+ * FunctionName : urlencode
+*******************************************************************************/
+/*int ICACHE_FLASH_ATTR urlencode(uint8 *d, uint8 *s, uint16 lend, uint16 lens)
+{
+ uint16 ret = 0;
+ if(s != NULL) while ((lens--) && (lend--) && (*s != '\0')) {
+ if ( (48 <= *s && *s <= 57) //0-9
+ || (65 <= *s && *s <= 90) //abc...xyz
+ || (97 <= *s && *s <= 122) //ABC...XYZ
+ || (*s == '~' || *s == '!' || *s == '*' || *s == '(' || *s == ')' || *s == '\'')) {
+ *d++ = *s++;
+ ret++;
+ } else {
+ if(lend >= 3) {
+ ret += 3;
+ lend -= 3;
+ *d++ = '%';
+ uint8 val = *s >> 4;
+ if(val <= 9) val += '0';
+ else val += 0x41 - 10;
+ *d++ = val;
+ val = *s++ & 0x0F;
+ if(val <= 9) val += '0';
+ else val += 0x41 - 10;
+ *d++ = val;
+ }
+ else break;
+ }
+ }
+ *d = '\0';
+ return ret;
+}*/
+/******************************************************************************
+ * FunctionName : htmlcode
+*******************************************************************************/
+int ICACHE_FLASH_ATTR htmlcode(uint8 *d, uint8 *s, uint16 lend, uint16 lens)
+{
+ uint16 ret = 0;
+ if(s != NULL) while ((lens--) && (lend--) && (*s != '\0')) {
+ if ( *s == 0x27 ) { // "'" '
+ if(lend >= 6) {
+ ret += 6;
+ lend -= 6;
+ s++;
+ *d++ = '&';
+ *d++ = 'a';
+ *d++ = 'p';
+ *d++ = 'o';
+ *d++ = 's';
+ *d++ = ';';
+ }
+ else break;
+ } else if ( *s == '"' ) { // "
+ if(lend >= 6) {
+ ret += 6;
+ lend -= 6;
+ s++;
+ *d++ = '&';
+ *d++ = 'q';
+ *d++ = 'u';
+ *d++ = 'o';
+ *d++ = 't';
+ *d++ = ';';
+ }
+ else break;
+ } else if ( *s == '&' ) { // &
+ if(lend >= 5) {
+ ret += 5;
+ lend -= 5;
+ s++;
+ *d++ = '&';
+ *d++ = 'a';
+ *d++ = 'm';
+ *d++ = 'p';
+ *d++ = ';';
+ }
+ else break;
+ } else if ( *s == '<' ) { // <
+ if(lend >= 4) {
+ ret += 4;
+ lend -= 4;
+ s++;
+ *d++ = '&';
+ *d++ = 'l';
+ *d++ = 't';
+ *d++ = ';';
+ }
+ else break;
+ } else if ( *s == '>' ) { // >
+ if(lend >= 4) {
+ ret += 4;
+ lend -= 4;
+ s++;
+ *d++ = '&';
+ *d++ = 'g';
+ *d++ = 't';
+ *d++ = ';';
+ }
+ else break;
+ } else {
+ *d++ = *s++;
+ ret++;
+ }
+ }
+ *d = '\0';
+ return ret;
+}
+//=============================================================================
+extern size_t rtl_strlen(const char *str);
+extern int rtl_strncmp(const char *s1, const char *s2, size_t n);
+
+uint8* ICACHE_FLASH_ATTR
+web_strnstr(const uint8* buffer, const uint8* token, int len)
+{
+ const uint8* p;
+ int tokenlen = rtl_strlen(token);
+ if (tokenlen == 0) {
+ return (uint8 *)buffer;
+ };
+ for (p = buffer; *p && (p + tokenlen <= buffer + len); p++) {
+ if ((*p == *token) && (rtl_strncmp(p, token, tokenlen) == 0)) {
+ return (uint8 *)p;
+ };
+ };
+ return NULL;
+}
+//=============================================================================
+static const uint8_t base64map[128] ICACHE_RODATA_ATTR =
+{
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255,
+ 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255,
+ 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255
+};
+//=============================================================================
+bool ICACHE_FLASH_ATTR base64decode(const uint8 *in, int len, uint8_t *out, int *outlen)
+{
+// uint8 *map = (uint8 *)UartDev.rcv_buff.pRcvMsgBuff;
+// ets_memcpy(map, base64map, 128);
+ uint8 *map = (uint8 *) base64map;
+ int g, t, x, y, z;
+ uint8_t c;
+ g = 3;
+ for (x = y = z = t = 0; x < len; x++) {
+ if ((c = map[in[x]&0x7F]) == 0xff) continue;
+ if (c == 254) { /* this is the end... */
+ c = 0;
+ if (--g < 0) return false;
+ }
+ else if (g != 3) return false; /* only allow = at end */
+ t = (t<<6) | c;
+ if (++y == 4) {
+ out[z++] = (uint8_t)((t>>16)&255);
+ if (g > 1) out[z++] = (uint8_t)((t>>8)&255);
+ if (g > 2) out[z++] = (uint8_t)(t&255);
+ y = t = 0;
+ }
+ /* check that we don't go past the output buffer */
+ if (z > *outlen) return false;
+ }
+ if (y != 0) return false;
+ *outlen = z;
+ return true;
+}
+//=============================================================================
+/* Table 6-bit-index-to-ASCII used for base64-encoding */
+const uint8_t base64_table[] = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
+ 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
+ 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ '+', '/'
+};
+// ld: PROVIDE ( base64_table = 0x3FFFD600 );
+//extern const uint8_t base64_table[];
+//=============================================================================
+/** Base64 encoding */
+size_t ICACHE_FLASH_ATTR base64encode(char* target, size_t target_len, const char* source, size_t source_len)
+{
+ size_t i;
+ sint8 j;
+ size_t target_idx = 0;
+ size_t longer = 3 - (source_len % 3);
+ size_t source_len_b64 = source_len + longer;
+ size_t len = (((source_len_b64) * 4) / 3);
+ uint8 x = 5;
+ uint8 current = 0;
+
+ if(target == NULL || target_len < len) return 0;
+
+ for (i = 0; i < source_len_b64; i++) {
+ uint8 b = (i < source_len ? source[i] : 0);
+ for (j = 7; j >= 0; j--, x--) {
+ uint8 shift = ((b & (1 << j)) != 0) ? 1 : 0;
+ current |= shift << x;
+ if (x == 0) {
+ target[target_idx++] = base64_table[current];
+ x = 6;
+ current = 0;
+ }
+ }
+ }
+ for (i = len - longer; i < len; i++) {
+ target[i] = '=';
+ }
+ return len;
+}
+/*
+//=============================================================================
+void ICACHE_FLASH_ATTR print_hex_dump(uint8 *buf, uint32 len, uint8 k)
+{
+ if(!system_get_os_print()) return; // if(*((uint8 *)(0x3FFE8000)) == 0) return;
+ uint32 ss[2];
+ ss[0] = 0x78323025; // "%02x"
+ ss[1] = k; // ","...'\0'
+ uint8* ptr = buf;
+ while(len--) {
+ if(len == 0) ss[1] = 0;
+ ets_printf((uint8 *)&ss[0], *ptr++);
+ }
+}
+*/
+//=============================================================================
+#define LowerCase(a) ((('A' <= a) && (a <= 'Z')) ? a + 32 : a)
+
+char* ICACHE_FLASH_ATTR word_to_lower_case(char* text) {
+ for(; *text ==' '; text++);
+ char* p = text;
+ for (; *p >= ' '; p++) {
+ *p = LowerCase(*p);
+ }
+ return text;
+}
+#if 0
+//=============================================================================
+/* char UpperCase(char ch) {
+ return (('a' <= ch) && (ch <= 'z')) ? ch - 32 : ch; }*/
+#define UpperCase(a) ((('a' <= a) && (a <= 'z')) ? a - 32 : a)
+
+char* ICACHE_FLASH_ATTR str_to_upper_case(char* text) {
+ char* p = text;
+ for (; *p; ++p) {
+ *p = UpperCase(*p);
+ }
+ return text;
+}
+#endif
+
diff --git a/RTLGDB/Project/web/web_utils.h b/RTLGDB/Project/web/web_utils.h
new file mode 100644
index 0000000..8d00c33
--- /dev/null
+++ b/RTLGDB/Project/web/web_utils.h
@@ -0,0 +1,48 @@
+ /******************************************************************************
+ * FileName: web_utils.h
+ * Alternate SDK
+ * Author: PV`
+ * (c) PV` 2015
+*******************************************************************************/
+
+#ifndef _INCLUDE_WEB_UTILS_H_
+#define _INCLUDE_WEB_UTILS_H_
+
+typedef enum {
+ SEG_ID_ROM = 0,
+ SEG_ID_SRAM,
+ SEG_ID_TCM,
+ SEG_ID_FLASH,
+ SEG_ID_SDRAM,
+ SEG_ID_SOC,
+ SEG_ID_CPU,
+ SEG_ID_ERR,
+ SEG_ID_MAX
+} SEG_ID;
+
+extern const uint32 tab_seg_def[];
+SEG_ID get_seg_id(uint32 addr, int32 size);
+
+int rom_atoi(const char *s);
+void copy_align4(void *ptrd, void *ptrs, uint32 len);
+uint32 hextoul(uint8 *s);
+uint32 ahextoul(uint8 *s);
+uint8 * cmpcpystr(uint8 *pbuf, uint8 *pstr, uint8 a, uint8 b, uint16 len);
+uint8 * web_strnstr(const uint8* buffer, const uint8* token, int n);
+bool base64decode(const uint8 *in, int len, uint8_t *out, int *outlen);
+size_t base64encode(char* target, size_t target_len, const char* source, size_t source_len);
+void strtomac(uint8 *s, uint8 *macaddr);
+//uint32 strtoip(uint8 *s); // ipaddr_addr();
+int urldecode(uint8 *d, uint8 *s, uint16 lend, uint16 lens);
+//int urlencode(uint8 *d, uint8 *s, uint16 lend, uint16 lens);
+int htmlcode(uint8 *d, uint8 *s, uint16 lend, uint16 lens);
+void print_hex_dump(uint8 *buf, uint32 len, uint8 k);
+// char* str_to_upper_case(char* text);
+uint32 str_array(uint8 *s, uint32 *buf, uint32 max_buf);
+uint32 str_array_w(uint8 *s, uint16 *buf, uint32 max_buf);
+uint32 str_array_b(uint8 *s, uint8 *buf, uint32 max_buf);
+char* word_to_lower_case(char* text);
+int rom_xstrcmp(char * pd, const char * ps);
+int rom_xstrcpy(char * pd, const char * ps);
+
+#endif /* _INCLUDE_WEB_UTILS_H_ */
diff --git a/RTLGDB/Project/web/web_websocket.c b/RTLGDB/Project/web/web_websocket.c
new file mode 100644
index 0000000..929b78c
--- /dev/null
+++ b/RTLGDB/Project/web/web_websocket.c
@@ -0,0 +1,352 @@
+/******************************************************************************
+ * FileName: web_websocket.c
+ * Description: websocket for web
+ * Author: pvvx
+ * 2016
+*******************************************************************************/
+#include "user_config.h"
+#ifdef WEBSOCKET_ENA
+#include "autoconf.h"
+#include "FreeRTOS.h"
+#include "task.h"
+#include "diag.h"
+//#include "bios.h"
+//#include "osapi.h"
+//#include "sdk/rom2ram.h"
+#include "lwip/tcp.h"
+#include "tcpsrv/tcp_srv_conn.h"
+#include "web_srv_int.h"
+#include "web_srv.h"
+#include "web_utils.h"
+#include "web_websocket.h"
+#include "websock.h"
+#include "rtl8195a/rtl_libc.h"
+#include "esp_comp.h"
+
+#if 0
+#undef DEBUGSOO
+#define DEBUGSOO 4
+#endif
+
+#define copy_s4d1 rtl_memcpy
+
+//#define mMIN(a, b) ((a 3
+ os_printf("ws%utx[%u] error %d!\n", opcode, raw_len, err);
+#endif
+ ((WEB_SRV_CONN *)ts_conn->linkd)->webflag |= SCB_DISCONNECT;
+ }
+ else {
+ if((opcode & WS_OPCODE_BITS) == WS_OPCODE_CLOSE) {
+ ((WEB_SRV_CONN *)ts_conn->linkd)->ws.flg |= WS_FLG_CLOSE;
+ }
+ }
+ return err;
+}
+//=============================================================================
+// websock_tx_close_err() - вывод сообщения закрытия или ошибки
+//=============================================================================
+err_t ICACHE_FLASH_ATTR
+websock_tx_close_err(TCP_SERV_CONN *ts_conn, uint32 err)
+{
+ uint8 uc[2];
+ uc[1] = err;
+ uc[0] = err>>8;
+ return websock_tx_frame(ts_conn, WS_OPCODE_CLOSE | WS_FRAGMENT_FIN, uc, 2);
+}
+//=============================================================================
+// websock_rx_data() прием данных
+//=============================================================================
+#define MAX_WS_DATA_BLK_SIZE (tcp_sndbuf(ts_conn->pcb)-8) // (TCP_MSS - 8)
+//=============================================================================
+bool ICACHE_FLASH_ATTR
+websock_rx_data(TCP_SERV_CONN *ts_conn)
+{
+// HTTP_CONN *CurHTTP;
+ WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
+ if(web_conn == NULL) return false;
+ WS_FRSTAT *ws = &web_conn->ws;
+ uint16 len;
+ uint8 *pstr;
+
+#if DEBUGSOO > 3
+ os_printf("ws_rx[%u]%u ", ts_conn->sizei, ts_conn->cntri);
+#endif
+ if(ts_conn->sizei == 0) return true; // докачивать
+ tcpsrv_unrecved_win(ts_conn);
+ if((ws->flg & WS_FLG_CLOSE) != 0) {
+ // убить буфер ts_conn->pbufi, конец давно :)
+ web_feee_bufi(ts_conn);
+ SetSCB(SCB_DISCONNECT);
+ return false;
+ }
+ if(ts_conn->sizei > MAX_RX_BUF_SIZE) {
+#if DEBUGSOO > 0
+ os_printf("ws:rxbuf_full! ");
+#endif
+ // убить буфер ts_conn->pbufi и ответить ошибкой WS_CLOSE_UNEXPECTED_ERROR
+ web_feee_bufi(ts_conn);
+ websock_tx_close_err(ts_conn, WS_CLOSE_MESSAGE_TOO_BIG); // WS_CLOSE_UNEXPECTED_ERROR);
+ SetSCB(SCB_DISCONNECT);
+ return false;
+ }
+ pstr = ts_conn->pbufi;// + ts_conn->cntri;
+ len = ts_conn->sizei;// - ts_conn->cntri;
+ while(ts_conn->cntri < ts_conn->sizei || (ws->flg & WS_FLG_FIN) != 0) {
+ pstr = ts_conn->pbufi;// + ts_conn->cntri;
+ len = ts_conn->sizei;// - ts_conn->cntri;
+ if((ws->flg & WS_FLG_FIN) != 0 // обработка
+ || ws->frame_len > ws->cur_len) {
+ ws->flg &= ~WS_FLG_FIN;
+ len = mMIN(ws->frame_len - ws->cur_len, mMIN(MAX_WS_DATA_BLK_SIZE, len));
+ // размаскировать
+ if((ws->flg & WS_FLG_MASK) != 0) WebsocketMask(ws, pstr, len);
+#if DEBUGSOO > 3
+ os_printf("wsfr[%u]blk[%u]at:%u ", ws->frame_len, len, ws->cur_len);
+#endif
+ switch(ws->status) {
+ case sw_frs_binary:
+#if DEBUGSOO > 1
+ os_printf("ws:bin ");
+#endif
+ if(ws->frame_len != 0) {
+ // пока просто эхо
+ uint32 opcode = WS_OPCODE_BINARY;
+ if(ws->cur_len != 0) opcode = WS_OPCODE_CONTINUE;
+ if(ws->frame_len == ws->cur_len + len) opcode |= WS_FRAGMENT_FIN;
+ if(websock_tx_frame(ts_conn, opcode, pstr, len) != ERR_OK) {
+ return false; // не докачивать, ошибка или закрытие
+ }
+ }
+ ws->cur_len += len;
+ ts_conn->cntri += len;
+ break;
+ case sw_frs_text:
+#if DEBUGSOO > 1
+ os_printf("ws:txt ");
+
+#if DEBUGSOO > 2
+ if(ws->frame_len != 0) {
+ uint8 tt = pstr[len];
+ pstr[len] = 0;
+ os_printf("'%s' ", pstr);
+ pstr[len] = tt;
+ }
+#endif
+#endif
+ if(ws->frame_len == ws->cur_len + len && ws->frame_len != 0) { // полное соо
+ web_conn->msgbufsize = tcp_sndbuf(ts_conn->pcb); // сколько можем выввести сейчас?
+ if (web_conn->msgbufsize < MIN_SEND_SIZE) {
+#if DEBUGSOO > 0
+ os_printf("ws:sndbuf=%u! ", web_conn->msgbufsize);
+#endif
+ websock_tx_close_err(ts_conn, WS_CLOSE_UNEXPECTED_ERROR);
+ SetSCB(SCB_FCLOSE|SCB_DISCONNECT);
+ return false;
+ }
+ web_conn->msgbufsize -= 16;
+ if(ws->frame_len == (sizeof(txt_wsping)-1) && rom_xstrcmp(pstr, txt_wsping) != 0){
+ copy_s4d1(pstr, (void *)txt_wspong, sizeof(txt_wspong) - 1);
+ if(websock_tx_frame(ts_conn, WS_OPCODE_TEXT | WS_FRAGMENT_FIN, pstr, sizeof(txt_wspong) - 1) != ERR_OK) {
+ return false; // не докачивать, ошибка или закрытие
+ }
+ }
+ else {
+ if(web_conn->msgbuf) os_free(web_conn->msgbuf);
+ web_conn->msgbuf = (uint8 *) os_malloc(web_conn->msgbufsize);
+ if (web_conn->msgbuf == NULL) {
+#if DEBUGSOO > 0
+ os_printf("ws:mem!\n");
+#endif
+ websock_tx_close_err(ts_conn, WS_CLOSE_UNEXPECTED_ERROR);
+ SetSCB(SCB_FCLOSE|SCB_DISCONNECT);
+ return false;
+ };
+ web_conn->msgbuflen = 0;
+ uint32 opcode;
+ if(CheckSCB(SCB_RETRYCB)) { // повторный callback? да
+ if(web_conn->func_web_cb != NULL) web_conn->func_web_cb(ts_conn);
+ if(!CheckSCB(SCB_RETRYCB)) {
+// ClrSCB(SCB_FCLOSE | SCB_DISCONNECT);
+ opcode = WS_OPCODE_CONTINUE | WS_FRAGMENT_FIN;
+ }
+ else opcode = WS_OPCODE_CONTINUE;
+ }
+ else {
+ pstr[len] = '\0';
+ uint8 *vstr = os_strchr(pstr, '=');
+ if(vstr != NULL) {
+ *vstr++ = '\0';
+ web_int_vars(ts_conn, pstr, vstr);
+ }
+ else {
+ web_conn->msgbuf[0] = 0;
+ web_int_callback(ts_conn, pstr);
+ }
+ if(CheckSCB(SCB_RETRYCB)) opcode = WS_OPCODE_TEXT;
+ else {
+// ClrSCB(SCB_FCLOSE | SCB_DISCONNECT);
+ opcode = WS_OPCODE_TEXT | WS_FRAGMENT_FIN;
+ }
+ }
+ if(web_conn->msgbuflen != 0) {
+ if(websock_tx_frame(ts_conn, opcode, web_conn->msgbuf, web_conn->msgbuflen) != ERR_OK) {
+ if(web_conn->msgbuf) os_free(web_conn->msgbuf);
+ web_conn->msgbuf = NULL;
+ return false; // не докачивать, ошибка или закрытие
+ }
+ }
+ if(web_conn->msgbuf) os_free(web_conn->msgbuf);
+ web_conn->msgbuf = NULL;
+ if(CheckSCB(SCB_RETRYCB)) return false;
+ }
+ }
+/*
+ if(0) {
+ uint32 opcode = WS_OPCODE_TEXT;
+ if(ws->cur_len != 0) opcode = WS_OPCODE_CONTINUE;
+ if(ws->frame_len == ws->cur_len + len) opcode |= WS_FRAGMENT_FIN;
+ if(websock_tx_frame(ts_conn, opcode, pstr, len) != ERR_OK) {
+ return false; // не докачивать, ошибка или закрытие
+ }
+ }
+*/
+ ws->cur_len += len;
+ ts_conn->cntri += len;
+ return true; // докачивать
+// break;
+// break;
+ case sw_frs_ping:
+#if DEBUGSOO > 1
+ os_printf("ws:ping ");
+#endif
+ {
+ uint32 opcode = WS_OPCODE_PONG;
+ if(ws->cur_len != 0) opcode = WS_OPCODE_CONTINUE;
+ if(ws->frame_len == ws->cur_len + len) opcode |= WS_FRAGMENT_FIN;
+ if(websock_tx_frame(ts_conn, opcode, pstr, len) != ERR_OK) {
+ return false; // не докачивать, ошибка или закрытие
+ }
+ }
+ ws->cur_len += len;
+ ts_conn->cntri += len;
+ return true; // докачивать
+// break;
+ case sw_frs_pong:
+#if DEBUGSOO > 1
+ os_printf("ws:pong ");
+#endif
+ ws->cur_len += len;
+ ts_conn->cntri += len;
+ break;
+// return true;
+ case sw_frs_close:
+#if DEBUGSOO > 1
+ os_printf("ws:close ");
+#endif
+// if((ws->flg & WS_FLG_CLOSE) == 0) {
+ {
+ if(len >= 2) {
+ uint32 close_code = (pstr[0]<<8) | pstr[1];
+#if DEBUGSOO > 1
+ os_printf("code:%d ", close_code);
+#endif
+ if(close_code == WS_CLOSE_NORMAL) websock_tx_close_err(ts_conn, WS_CLOSE_NORMAL);
+ // else websock_tx_frame(ts_conn, WS_OPCODE_CLOSE | WS_FRAGMENT_FIN, NULL, 0);
+ }
+ else
+ {
+ websock_tx_close_err(ts_conn, WS_CLOSE_NORMAL);
+ // websock_tx_frame(ts_conn, WS_OPCODE_CLOSE | WS_FRAGMENT_FIN, NULL, 0);
+ }
+ }
+ ts_conn->flag.pcb_time_wait_free = 1;
+ SetSCB(SCB_DISCONNECT);
+// ts_conn->cntri = ts_conn->sizei;
+/* ws->cur_len += len;
+ ts_conn->cntri += len; */
+ return false;
+ default:
+#if DEBUGSOO > 0
+ os_printf("ws:f?! ");
+#endif
+ websock_tx_close_err(ts_conn, WS_CLOSE_UNEXPECTED_ERROR);
+ SetSCB(SCB_DISCONNECT);
+ // ts_conn->cntri = ts_conn->sizei;
+ return false;
+ }
+ }
+ else
+ if(ws->cur_len >= ws->frame_len) { // прием и разбор нового фрейма
+ if((ws->flg & WS_FLG_FIN) != 0) { // обработка
+#if DEBUGSOO > 3
+ os_printf("ws_rx:fin=%u ", ws->cur_len);
+#endif
+ }
+ else {
+ uint32 ret = WebsocketHead(ws, pstr, len);
+ if(ret >= WS_CLOSE_NORMAL) { // error или close
+
+#if DEBUGSOO > 0
+ os_printf("ws:txerr=%u ", ret);
+#endif
+ websock_tx_close_err(ts_conn, ret);
+// ts_conn->cntri = ts_conn->sizei; // убить буфер ts_conn->pbufi
+ return false; // error
+ }
+ else if(ret == 0) {
+#if DEBUGSOO > 3
+ os_printf("ws_rx... ");
+#endif
+ return true; // докачивать
+ }
+ ts_conn->cntri += ws->head_len; // вычесть заголовок
+/*
+ switch(ws->status) {
+ case sw_frs_binary:
+ break;
+ case sw_frs_text:
+ if(ws->frame_len > MAX_RX_BUF_SIZE) {
+ websock_tx_close_err(ts_conn, WS_CLOSE_MESSAGE_TOO_BIG);
+ return false;
+ }
+ break;
+ }
+*/
+ }
+ }
+#if DEBUGSOO > 3
+ os_printf("trim%u-%u ", ts_conn->sizei, ts_conn->sizei - ts_conn->cntri );
+#endif
+ if(!web_trim_bufi(ts_conn, &ts_conn->pbufi[ts_conn->cntri], ts_conn->sizei - ts_conn->cntri)) {
+#if DEBUGSOO > 0
+ os_printf("ws:trim_err! ");
+#endif
+ // убить буфер ts_conn->pbufi и ответить ошибкой WS_CLOSE_UNEXPECTED_ERROR
+ websock_tx_close_err(ts_conn, WS_CLOSE_UNEXPECTED_ERROR);
+ SetSCB(SCB_DISCONNECT);
+// ts_conn->cntri = ts_conn->sizei;
+ return false;
+ };
+ }
+ return false; // не докачивать, ошибка или закрытие
+}
+//=============================================================================
+//=============================================================================
+#endif // WEBSOCKET_ENA
+
+
diff --git a/RTLGDB/Project/web/web_websocket.h b/RTLGDB/Project/web/web_websocket.h
new file mode 100644
index 0000000..0d5aac6
--- /dev/null
+++ b/RTLGDB/Project/web/web_websocket.h
@@ -0,0 +1,18 @@
+#ifndef _WEB_WEBSOCKET_H_
+/******************************************************************************
+ * FileName: web_websocket.h
+ * Description: websocket for web ESP8266
+ * Author: PV`
+ * (c) PV` 2016
+*******************************************************************************/
+#define _WEB_WEBSOCKET_H_
+#include "user_config.h"
+#ifdef WEBSOCKET_ENA
+#include "websock.h"
+
+err_t websock_tx_close_err(TCP_SERV_CONN *ts_conn, uint32 err);
+bool websock_rx_data(TCP_SERV_CONN *ts_conn);
+err_t websock_tx_frame(TCP_SERV_CONN *ts_conn, uint32 opcode, uint8 *raw_data, uint32 raw_len);
+
+#endif // WEBSOCKET_ENA
+#endif /* _WEB_WEBSOCKET_H_ */
diff --git a/RTLGDB/Project/web/websock.c b/RTLGDB/Project/web/websock.c
new file mode 100644
index 0000000..d9e2efc
--- /dev/null
+++ b/RTLGDB/Project/web/websock.c
@@ -0,0 +1,245 @@
+/******************************************************************************
+ * FileName: websock.c
+ * Description: websocket for web ESP8266
+ * Author: PV`
+ * (c) PV` 2016
+*******************************************************************************/
+#include "user_config.h"
+#ifdef WEBSOCKET_ENA
+#include "autoconf.h"
+#include "FreeRTOS.h"
+#include "task.h"
+#include "diag.h"
+#include "tcpsrv/tcp_srv_conn.h"
+#include "web_utils.h" // base64encode()
+#include "web_srv.h"
+//#include "phy/phy.h"
+#include "device_lock.h"
+#include "lwip/tcp.h"
+#include "websock.h"
+#include "rtl8195a/rtl_libc.h"
+#include "esp_comp.h"
+#include "hal_crypto.h"
+
+// HTTP/1.1 101 Web Socket Protocol Handshake\r\n
+const uint8 WebSocketHTTPOkKey[] ICACHE_RODATA_ATTR = "HTTP/1.1 101 Switching Protocols\r\nAccess-Control-Allow-Origin: *\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: %s\r\n\r\n";
+const uint8 WebSocketAddKey[] ICACHE_RODATA_ATTR = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
+const uint8 *HTTPUpgrade = "Upgrade:";
+const uint8 *HTTPwebsocket = "websocket";
+const uint8 *HTTPSecWebSocketKey = "Sec-WebSocket-Key:";
+
+//=============================================================================
+// WebSocketAcceptKey()
+// 1) взять строковое значение из заголовка Sec-WebSocket-Key и объединить со
+// строкой 258EAFA5-E914-47DA-95CA-C5AB0DC85B11
+// 2) вычислить бинарный хеш SHA-1 (бинарная строка из 20 символов) от полученной
+// в первом пункте строки
+// 3) закодировать хеш в Base64
+// skey[24+36]:'dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
+// cha:'b37a4f2cc0624f1690f64606cf385945b2bec4ea'
+// key[28]:'s3pPLMBiTxaQ9kYGzzhZRbK+xOo='
+//=============================================================================
+uint8 buff[maxsizeWebSocketKey + sizeWebSocketAddKey]; // [68]
+bool ICACHE_FLASH_ATTR WebSocketAcceptKey(uint8* dkey, uint8* skey)
+{
+ int len = 0;
+ bool ret = false;
+ uint8 keybuf[CRYPTO_SHA1_DIGEST_LENGTH];
+ uint8 * buff = os_malloc(maxsizeWebSocketKey + sizeWebSocketAddKey);
+ if(buff) {
+ while(skey[len] >= '+' && len < maxsizeWebSocketKey) {
+ buff[len] = skey[len];
+ len++;
+ };
+ if(len > minsizeWebSocketKey) {
+ rtl_memcpy(&buff[len], WebSocketAddKey, sizeWebSocketAddKey+1);
+ device_mutex_lock(RT_DEV_LOCK_CRYPTO);
+ rtl_crypto_sha1(buff, len + sizeWebSocketAddKey, keybuf);
+ device_mutex_unlock(RT_DEV_LOCK_CRYPTO);
+// rtl_cryptoEngine_info();
+ len = base64encode(dkey, FileNameSize, keybuf, CRYPTO_SHA1_DIGEST_LENGTH);
+#if DEBUGSOO > 2
+ os_printf("\ncha:'");
+ print_hex_dump(keybuf, CRYPTO_SHA1_DIGEST_LENGTH, '\0');
+ os_printf("'\n");
+ os_printf("key[%u]:'%s'\n", len, dkey);
+#endif
+ ret = true;
+ }
+ os_free(buff);
+ }
+ return ret;
+
+}
+//=============================================================================
+// websock_mask() размаскирование блока
+//=============================================================================
+void ICACHE_FLASH_ATTR
+WebsocketMask(WS_FRSTAT *ws, uint8 *raw_data, uint32 raw_len)
+{
+ uint32 i, x = ws->cur_len;
+#if DEBUGSOO > 3
+ os_printf("mask[%u]%u ", raw_len, x);
+#endif
+ for (i = 0; i < raw_len; i++) {
+ raw_data[i] ^= ws->mask.uc[x++ & 3];
+ }
+}
+//=============================================================================
+// websock_head() разбор заголовка
+//=============================================================================
+uint32 ICACHE_FLASH_ATTR
+WebsocketHead(WS_FRSTAT *ws, uint8 *raw_data, uint32 raw_len)
+{
+ // определить размер заголовка фрейма
+ uint32 head_len = 2;
+ if(raw_len < head_len) return 0; // докачивать
+ uint32 data_len = raw_data[1] & WS_SIZE1_BITS;
+ if(data_len == 127) head_len = 10;
+ else if(data_len == 126) head_len = 4;
+ if(raw_data[1] & WS_MASK_FLG) head_len += 4;
+ if(raw_len < head_len) return 0; // докачивать
+ ws->head_len = head_len;
+ ws->cur_len = 0;
+ ws->flg = 0;
+ data_len = raw_data[1] & WS_SIZE1_BITS;
+ if(data_len >= 126) {
+ if(data_len == 127) {
+ uint32 i;
+ for(i = 3; i < 6; i++) {
+ if(raw_data[i] != 0) {
+ ws->status = sw_frs_close;
+ ws->frame_len = 0;
+ return WS_CLOSE_MESSAGE_TOO_BIG;
+ }
+ }
+ data_len = (raw_data[6] << 24) | (raw_data[7] << 16) | (raw_data[8] << 8) | raw_data[9];
+ }
+ else {
+ data_len = (raw_data[2] << 8) | raw_data[3];
+ }
+ }
+ if(raw_data[1] & WS_MASK_FLG) {
+ ws->flg |= WS_FLG_MASK;
+ ws->mask.uc[0] = raw_data[head_len-4];
+ ws->mask.uc[1] = raw_data[head_len-3];
+ ws->mask.uc[2] = raw_data[head_len-2];
+ ws->mask.uc[3] = raw_data[head_len-1];
+ }
+// else ws->mask = 0;
+ uint8 opcode = raw_data[0] & WS_OPCODE_BITS;
+ switch(opcode) {
+ case WS_OPCODE_PING: // эхо - дублировать прием
+ raw_data[0] &= ~WS_FRAGMENT_FIN;
+ raw_data[0] |= WS_OPCODE_PONG;
+ ws->status = sw_frs_pong;
+ ws->frame_len = data_len;
+ break;
+ case WS_OPCODE_PONG: // эхо - дублировать прием
+ ws->status = sw_frs_ping;
+ ws->frame_len = data_len;
+ break;
+ case WS_OPCODE_CONTINUE: // продолжить
+ if(ws->status == sw_frs_pong) {
+ ws->frame_len = data_len;
+ break;
+ }
+ else ws->frame_len += data_len;
+ break;
+ case WS_OPCODE_CLOSE: //
+ ws->status = sw_frs_close;
+ ws->frame_len = data_len;
+ break;
+ case WS_OPCODE_TEXT:
+ ws->status = sw_frs_text;
+ ws->frame_len = data_len;
+ break;
+ case WS_OPCODE_BINARY:
+ ws->status = sw_frs_binary;
+ ws->frame_len = data_len;
+ break;
+ default:
+ ws->status = sw_frs_close;
+ ws->frame_len = 0;
+ return WS_CLOSE_WRONG_TYPE;
+ }
+// uint32 len = mMIN(raw_len - head_len, data_len);
+// if((ws->flg & WS_FLG_MASK) != 0) websock_mask(ws, &raw_data[head_len], mMIN(raw_len - head_len, len));
+// ws->cur_len += len;
+ if((raw_data[0] & WS_FRAGMENT_FIN) != 0) { // конец - данные на обработку
+ ws->flg |= WS_FLG_FIN;
+ }
+#if DEBUGSOO > 1
+ os_printf("ws#%02xrx[%u] ", raw_data[0], data_len);
+#endif
+ return 1;
+/*
+ if(data_len + head_len <= raw_len) { // весь пакет уже в буфере?
+ return 1;
+ }
+ return 0; // докачивать */
+}
+//=============================================================================
+// websock_tx_frame() - передача фрейма
+//=============================================================================
+err_t ICACHE_FLASH_ATTR
+WebsocketTxFrame(TCP_SERV_CONN *ts_conn, uint32 opcode, uint8 *raw_data, uint32 raw_len)
+{
+ union {
+ uint8 uc[8];
+ uint16 uw[4];
+ uint32 ud[2];
+ }head;
+ union {
+ uint8 uc[4];
+ uint16 uw[2];
+ uint32 ud;
+ }mask;
+ if(raw_data == NULL) raw_len = 0;
+ head.ud[0] = opcode;
+ uint32 head_len;
+ if(raw_len > 126) {
+ head.uc[1] = 126;
+ head.uc[2] = raw_len>>8;
+ head.uc[3] = raw_len;
+ head_len = 4;
+ }
+ else {
+ head.uc[1] = raw_len;
+ head_len = 2;
+ };
+ if(opcode & (WS_MASK_FLG << 8)) {
+ mask.ud ^= rand();
+ head.uc[1] |= WS_MASK_FLG;
+ head.uc[head_len] = mask.uc[0];
+ head.uc[head_len+1] = mask.uc[1];
+ head.uc[head_len+2] = mask.uc[2];
+ head.uc[head_len+3] = mask.uc[3];
+ head_len += 4;
+ }
+ uint32 len = tcp_sndbuf(ts_conn->pcb);
+ err_t err = 1; // ERR_BUF;
+ if(len >= raw_len + head_len) {
+#if DEBUGSOO > 1
+ os_printf("ws#%02xtx[%u] ", head.uc[0], raw_len);
+#endif
+ ts_conn->flag.nagle_disabled = 0;
+ tcp_nagle_disable(ts_conn->pcb);
+ err = tcpsrv_int_sent_data(ts_conn, head.uc, head_len);
+ ts_conn->flag.nagle_disabled = 1;
+ if(err == ERR_OK && raw_len != 0) {
+ if(opcode & (WS_MASK_FLG << 8)) {
+ uint32 i;
+ for (i = 0; i < raw_len; i++) {
+ raw_data[i] ^= mask.uc[i & 3];
+ }
+ }
+ err = tcpsrv_int_sent_data(ts_conn, raw_data, raw_len);
+ }
+ }
+ return err;
+}
+
+
+#endif // WEBSOCKET_ENA
+
diff --git a/RTLGDB/Project/web/websock.h b/RTLGDB/Project/web/websock.h
new file mode 100644
index 0000000..43c9c3f
--- /dev/null
+++ b/RTLGDB/Project/web/websock.h
@@ -0,0 +1,110 @@
+/*
+ * File: websock.h
+ * Small WEB server ESP8266EX
+ * Author: PV`
+ */
+
+#ifndef _WEBSOCK_H_
+#define _WEBSOCK_H_
+#include "lwip/err.h"
+#include "tcpsrv/tcp_srv_conn.h"
+
+//#define WS_NONBLOCK 0x02
+
+/*
+ 0 1 2 3
+ 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
+ +-+-+-+-+-------+-+-------------+-------------------------------+
+ |F|R|R|R| опкод |М| Длина тела | Расширенная длина тела |
+ |I|S|S|S|(4бита)|А| (7бит) | (2 байта) |
+ |N|V|V|V| |С| |(если длина тела==126 или 127) |
+ | |1|2|3| |Рљ| | |
+ | | | | | |Рђ| | |
+ +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
+ |4 5 6 7 |
+ | Продолжение расширенной длины тела, если длина тела = 127 |
+ + - - - - - - - - - - - - - - - +-------------------------------+
+ |8 9 10 11 |
+ | | Ключ маски, если МАСКА = 1 |
+ +-------------------------------+-------------------------------+
+ |12 13 14 15 |
+ | Ключ маски (продолжение) | Данные фрейма ("тело") |
+ +-------------------------------- - - - - - - - - - - - - - - - +
+ |16 17 18 19 |
+ : Данные продолжаются ... :
+ + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
+ | Данные продолжаются ... |
+ +---------------------------------------------------------------+
+
+*/
+
+#define WS_FRAGMENT_FIN 0x80
+//#define WS_RSVD_BITS (7 << 4)
+#define WS_OPCODE_BITS 0x7F
+#define WS_OPCODE_CONTINUE 0x0 // фрейм-продолжение для фрагментированного сообщения
+#define WS_OPCODE_TEXT 0x1 // текстовый фрейм
+#define WS_OPCODE_BINARY 0x2 // двоичный фрейм
+#define WS_OPCODE_CLOSE 0x8 // закрытие соединения
+#define WS_OPCODE_PING 0x9
+#define WS_OPCODE_PONG 0xa
+#define WS_MASK_FLG (1 << 7)
+#define WS_SIZE1_BITS 0x7F
+
+
+#define WS_CLOSE_NORMAL 1000
+#define WS_CLOSE_GOING_AWAY 1001
+#define WS_CLOSE_PROTOCOL_ERROR 1002
+#define WS_CLOSE_NOT_ALLOWED 1003
+#define WS_CLOSE_RESERVED 1004
+#define WS_CLOSE_NO_CODE 1005
+#define WS_CLOSE_DIRTY 1006
+#define WS_CLOSE_WRONG_TYPE 1007
+#define WS_CLOSE_POLICY_VIOLATION 1008
+#define WS_CLOSE_MESSAGE_TOO_BIG 1009
+#define WS_CLOSE_UNEXPECTED_ERROR 1011
+
+typedef struct _WS_FRSTAT
+{
+ uint32 frame_len; // размер данных в заголовке фрейма
+ uint32 cur_len; // счетчик обработанных данных
+ union {
+ unsigned char uc[4];
+ unsigned int ud;
+ } mask; // маска принимаемых данных
+ uint8 status;
+ uint8 flg;
+ uint8 head_len;
+} WS_FRSTAT; // __attribute__((packed))
+
+#define WS_FLG_MASK 0x01
+#define WS_FLG_FIN 0x02
+#define WS_FLG_CLOSE 0x04 // уже передано WS_CLOSE
+
+enum WS_FRAME_STATE {
+ sw_frs_none = 0,
+ sw_frs_text,
+ sw_frs_binary,
+ sw_frs_close,
+ sw_frs_ping,
+ sw_frs_pong
+};
+
+extern const uint8 WebSocketHTTPOkKey[]; // ICACHE_RODATA_ATTR = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept:%s\r\n\r\n"
+extern const uint8 WebSocketAddKey[]; // ICACHE_RODATA_ATTR = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
+#define sizeWebSocketAddKey 36
+#define maxsizeWebSocketKey 64
+#define minsizeWebSocketKey 8
+extern const uint8 *HTTPUpgrade; // = "Upgrade:";
+#define sizeHTTPUpgrade 8
+extern const uint8 *HTTPwebsocket; // = "websocket";
+#define sizeHTTPwebsocket 9
+extern const uint8 *HTTPSecWebSocketKey; // = "Sec-WebSocket-Key:";
+#define sizeHTTPSecWebSocketKey 18
+
+
+bool WebSocketAcceptKey(uint8* dkey, uint8* skey);
+void WebsocketMask(WS_FRSTAT *ws, uint8 *raw_data, uint32 raw_len);
+uint32 WebsocketHead(WS_FRSTAT *ws, uint8 *raw_data, uint32 raw_len);
+err_t WebsocketTxFrame(TCP_SERV_CONN *ts_conn, uint32 opcode, uint8 *raw_data, uint32 raw_len);
+
+#endif /* _WEBSOCK_H_ */
diff --git a/RTLGDB/Project/webfs/webfs.c b/RTLGDB/Project/webfs/webfs.c
new file mode 100644
index 0000000..8cf5c43
--- /dev/null
+++ b/RTLGDB/Project/webfs/webfs.c
@@ -0,0 +1,483 @@
+/*********************************************************************
+ * WEBFS.c
+ * RTL871x Flash WEB File System v1.0
+ ********************************************************************/
+#include "autoconf.h"
+#include "FreeRTOS.h"
+#include "task.h"
+#include "diag.h"
+#include
+#include
+#include "device_lock.h"
+#include "flash_api.h"
+//#include "flash_eep.h"
+
+#include "webfs/webfs.h"
+#include "rtl8195a/rtl_libc.h"
+#include "esp_comp.h"
+
+
+#define WEBFS_CODE_ATTR
+#define WEBFS_DATA_ATTR
+
+#define web_mutex_lock() device_mutex_lock(RT_DEV_LOCK_FLASH)
+#define web_mutex_unlock() device_mutex_unlock(RT_DEV_LOCK_FLASH)
+
+// Supports long file names to 64 characters
+#define MAX_FILE_NAME_LEN 64 // VarNameSize
+uint32 disk_base_addr WEBFS_DATA_ATTR;
+#define WEBFS_HEAD_ADDR disk_base_addr
+/*
+ *
+ * Structure:
+ *
+ * [F][W][E][B][uint8 Ver Hi][uint8 Ver Lo] // заголовок диска
+ * [uint16 Number of Files] // кол-во файлов на диске
+ * [Name Hash 0]...[Name Hash N] // uint16 типа хеш на каждое имя файла
+ * [File Record 0]...[File Record N] // uint32 указатели на адреса структур файлов, относительно начала диска
+ *
+ * File Record Structure:
+ * [uint32 Len] размер файла с заголовком
+ * [uint16 HeadLen] длина заголовка, включая размер, флаг, имя (адрес данных - адрес позиции len)
+ * [uint16 Flags] бит 0 =1 - файл сжат GZIP, бит 1 = 1 - парсится - имеет динамические переменные
+ * [File Name, 0] РРјСЏ файла СЃ "РЎР" терминатором
+ * [File Data] данные файла
+ *
+ * Name hash (2 uint8s) is calculated as follows:
+ * hash = 0
+ * for each(uint8 in name)
+ * hash += uint8
+ * hash <<= 1
+ *
+ * Technically this means the hash only includes the
+ * final 15 characters of a name.
+ *
+ * String FileNmae Structure (1 to 64 uint8s):
+ * ["path/to/file.ext"][0x00]
+ *
+ *
+ * Current version is 1.0
+ */
+// Lock WEBFS access during the upgrade
+volatile bool isWEBFSLocked WEBFS_DATA_ATTR;
+// Track the WEBFS File Handles
+// WEBFSStubs[0] is reserved for internal use (FAT access)
+WEBFS_STUB WEBFSStubs[MAX_WEBFS_OPENFILES+1] WEBFS_DATA_ATTR; // + HANDLE = 0
+// FAT record cache
+WEBFS_FAT_RECORD fatCache WEBFS_DATA_ATTR;
+// ID of currently loaded fatCache
+static uint32 fatCacheID WEBFS_DATA_ATTR;
+// Number of files in this WEBFS image
+uint16 numFiles WEBFS_DATA_ATTR;
+
+static void GetFATRecord(uint16 fatID);
+static void WEBFS_Update(void);
+
+/*****************************************************************************
+ Function:
+ void WEBFSInit(void)
+ Description:
+ Web Disk Init
+ *****************************************************************************/
+void WEBFS_CODE_ATTR WEBFSInit(void)
+{
+ disk_base_addr = WEBFS_base_addr();
+ os_memset((char *) &WEBFSStubs, 0xff, sizeof(WEBFSStubs));
+ // Validate the image and load numFiles
+ WEBFS_Update();
+#if DEBUGSOO > 0
+ os_printf("\nDisk init: %d files, addr = %p\n", numFiles, disk_base_addr);
+#endif
+ // тут надо расчет контрольки тела диска или другой контроль...
+ if(numFiles == 0) isWEBFSLocked = true;
+ else isWEBFSLocked = false;
+}
+/*****************************************************************************
+ Function:
+ WEBFS_HANDLE WEBFSOpen(uint8* cFile)
+
+ Description:
+ Opens a file in the WEBFS2 file system.
+
+ Precondition:
+ None
+
+ Parameters:
+ cFile - a null terminated file name to open
+
+ Returns:
+ An WEBFS_HANDLE to the opened file if found, or WEBFS_INVALID_HANDLE
+ if the file could not be found or no free handles exist.
+ ***************************************************************************/
+WEBFS_HANDLE WEBFS_CODE_ATTR WEBFSOpen(uint8* cFile)
+{
+ WEBFS_HANDLE hWEBFS;
+ uint16 nameHash;
+ int i, len = 0;
+ uint16 hashCache[16];
+ uint8 bufname[MAX_FILE_NAME_LEN];
+ uint8 *ptr;
+
+ // Make sure WEBFS is unlocked and we got a filename
+ if(*cFile == '\0' || isWEBFSLocked == true)
+ return WEBFS_INVALID_HANDLE;
+
+ // Calculate the name hash to speed up searching
+ for(nameHash = 0, ptr = cFile; *ptr != '\0'; ptr++)
+ {
+ nameHash += *ptr;
+ nameHash <<= 1;
+ len++;
+ }
+ // Find a free file handle to use
+ for(hWEBFS = 1; hWEBFS <= MAX_WEBFS_OPENFILES; hWEBFS++)
+ if(WEBFSStubs[hWEBFS].addr == WEBFS_INVALID) break;
+ if(hWEBFS == MAX_WEBFS_OPENFILES)
+ return WEBFS_INVALID_HANDLE;
+ // Read in hashes, and check remainder on a match. Store 8 in cache for performance
+ for(i = 0; i < numFiles; i++) {
+ // For new block of 8, read in data
+ if((i & 0x0F) == 0) {
+ WEBFSStubs[0].addr = 12 + i*2;
+ WEBFSStubs[0].bytesRem = 32;
+ WEBFSGetArray(0, (uint8*)hashCache, 32);
+ }
+ // If the hash matches, compare the full filename
+ if(hashCache[i&0x0F] == nameHash)
+ {
+ GetFATRecord(i);
+ // filename comparison
+ WEBFSStubs[0].addr = fatCache.string;
+ WEBFSStubs[0].bytesRem = MAX_FILE_NAME_LEN;
+ WEBFSGetArray(0, bufname, MAX_FILE_NAME_LEN);
+ if(os_strncmp(cFile, bufname, len) == 0) { // Filename matches, so return true
+ WEBFSStubs[hWEBFS].addr = fatCache.data;
+ WEBFSStubs[hWEBFS].bytesRem = fatCache.len;
+ WEBFSStubs[hWEBFS].fatID = i;
+ return hWEBFS;
+ }
+ }
+ }
+ // No file name matched, so return nothing
+ return WEBFS_INVALID_HANDLE;
+}
+/*****************************************************************************
+ Function: void WEBFSClose(WEBFS_HANDLE hWEBFS)
+ Summary: Closes a file.
+ Returns: None
+ ***************************************************************************/
+void WEBFS_CODE_ATTR WEBFSClose(WEBFS_HANDLE hWEBFS)
+{
+ if(hWEBFS != 0 && hWEBFS <= MAX_WEBFS_OPENFILES)
+ WEBFSStubs[hWEBFS].addr = WEBFS_INVALID;
+}
+/*****************************************************************************
+ Function: uint16 WEBFSGetArray(WEBFS_HANDLE hWEBFS, uint8* cData, uint16 wLen)
+ Description: Reads a series of uint8s from a file.
+ Precondition: The file handle referenced by hWEBFS is already open.
+ Parameters:
+ hWEBFS - the file handle from which to read
+ cData - where to store the uint8s that were read
+ wLen - how many uint8s to read
+ Returns:
+ The number of uint8s successfully read. If this is less than wLen,
+ an EOF occurred while attempting to read.
+ ***************************************************************************/
+uint16 WEBFS_CODE_ATTR WEBFSGetArray(WEBFS_HANDLE hWEBFS, uint8* cData, uint16 wLen)
+{
+ // Make sure we're reading a valid address
+ if(hWEBFS > MAX_WEBFS_OPENFILES) return 0;
+
+ // Determine how many we can actually read
+ if(wLen > WEBFSStubs[hWEBFS].bytesRem) wLen = WEBFSStubs[hWEBFS].bytesRem;
+ // Make sure we're reading a valid address
+ if(WEBFSStubs[hWEBFS].addr == WEBFS_INVALID || wLen == 0) return 0;
+
+ if(cData != NULL) {
+
+ // Read the data
+ web_mutex_lock();
+// if(wLen < 16)
+ flash_stream_read(&flashobj, WEBFSStubs[hWEBFS].addr + WEBFS_HEAD_ADDR, wLen, cData);
+// else flash_burst_read(&flashobj, WEBFSStubs[hWEBFS].addr + WEBFS_HEAD_ADDR, wLen, cData);
+ web_mutex_unlock();
+
+// if(spi_flash_read(WEBFSStubs[hWEBFS].addr+WEBFS_HEAD_ADDR, cData, wLen) != SPI_FLASH_RESULT_OK)
+// return 0;
+ };
+ WEBFSStubs[hWEBFS].addr += wLen;
+ WEBFSStubs[hWEBFS].bytesRem -= wLen;
+ return wLen;
+}
+/*****************************************************************************
+ Function:
+ bool WEBFSSeek(WEBFS_HANDLE hWEBFS, uint32 dwOffset, WEBFS_SEEK_MODE tMode)
+ Description: Moves the current read pointer to a new location.
+ Precondition: The file handle referenced by hWEBFS is already open.
+ Parameters:
+ hWEBFS - the file handle to seek with
+ dwOffset - offset from the specified position in the specified direction
+ tMode - one of the WEBFS_SEEK_MODE constants
+ Returns:
+ true - the seek was successful
+ false - either the new location or the handle itself was invalid
+ ***************************************************************************/
+bool WEBFS_CODE_ATTR WEBFSSeek(WEBFS_HANDLE hWEBFS, uint32 dwOffset, WEBFS_SEEK_MODE tMode)
+{
+ uint32 temp;
+
+ // Make sure a valid file is open
+ if(hWEBFS > MAX_WEBFS_OPENFILES || WEBFSStubs[hWEBFS].addr == WEBFS_INVALID)
+ return false;
+
+ switch(tMode)
+ {
+ // Seek offset uint8s from start
+ case WEBFS_SEEK_START:
+ temp = WEBFSGetSize(hWEBFS);
+ if(dwOffset > temp)
+ return false;
+
+ WEBFSStubs[hWEBFS].addr = WEBFSGetStartAddr(hWEBFS) + dwOffset;
+ WEBFSStubs[hWEBFS].bytesRem = temp - dwOffset;
+ return true;
+
+ // Seek forwards offset uint8s
+ case WEBFS_SEEK_FORWARD:
+ if(dwOffset > WEBFSStubs[hWEBFS].bytesRem)
+ return false;
+
+ WEBFSStubs[hWEBFS].addr += dwOffset;
+ WEBFSStubs[hWEBFS].bytesRem -= dwOffset;
+ return true;
+
+ // Seek backwards offset uint8s
+ case WEBFS_SEEK_REWIND:
+ temp = WEBFSGetStartAddr(hWEBFS);
+ if(WEBFSStubs[hWEBFS].addr < temp + dwOffset)
+ return false;
+
+ WEBFSStubs[hWEBFS].addr -= dwOffset;
+ WEBFSStubs[hWEBFS].bytesRem += dwOffset;
+ return true;
+
+ // Seek so that offset uint8s remain in file
+ case WEBFS_SEEK_END:
+ temp = WEBFSGetSize(hWEBFS);
+ if(dwOffset > temp)
+ return false;
+
+ WEBFSStubs[hWEBFS].addr = WEBFSGetEndAddr(hWEBFS) - dwOffset;
+ WEBFSStubs[hWEBFS].bytesRem = dwOffset;
+ return true;
+
+ default:
+ return false;
+ }
+}
+/*****************************************************************************
+ Function: static void GetFATRecord(uint16 fatID)
+ Description: Loads the FAT record for a specified handle.
+ Precondition: None
+ Parameters: fatID - the ID of the file whose FAT is to be loaded
+ Returns: None
+ Remarks: The FAT record will be stored in fatCache.
+ ***************************************************************************/
+static void WEBFS_CODE_ATTR GetFATRecord(uint16 fatID)
+{
+ WEBFS_FHEADER fhead;
+ if(fatID == fatCacheID || fatID >= numFiles) return;
+ // Read the FAT record to the cache
+ WEBFSStubs[0].bytesRem = sizeof(fhead) + 4;
+ WEBFSStubs[0].addr = 12 + numFiles*2 + fatID *4;
+ WEBFSGetArray(0, (uint8 *)&fatCache.data, 4);
+ WEBFSStubs[0].addr = fatCache.data;
+ WEBFSGetArray(0, (uint8 *)&fhead, sizeof(fhead));
+ fatCache.len = fhead.blksize - fhead.headlen;
+ fatCache.string = fatCache.data + 8;
+ fatCache.flags = fhead.flags;
+ fatCache.data = fatCache.data + fhead.headlen;
+ fatCacheID = fatID;
+}
+/*****************************************************************************
+ Function: uint16 WEBFSGetFlags(WEBFS_HANDLE hWEBFS)
+ Description: Reads a file's flags.
+ Precondition: The file handle referenced by hWEBFS is already open.
+ Parameters: hWEBFS - the file handle from which to read the metadata
+ Returns: The flags that were associated with the file
+ ***************************************************************************/
+uint16 WEBFS_CODE_ATTR WEBFSGetFlags(WEBFS_HANDLE hWEBFS)
+{
+ // Make sure a valid file is open
+ if(hWEBFS > MAX_WEBFS_OPENFILES || WEBFSStubs[hWEBFS].addr == WEBFS_INVALID)
+ return 0;
+
+ //move to the point for reading
+ GetFATRecord(WEBFSStubs[hWEBFS].fatID);
+ return fatCache.flags;
+}
+/*****************************************************************************
+ Function: uint32 WEBFSGetSize(WEBFS_HANDLE hWEBFS)
+ Description: Reads the size of a file.
+ Precondition: The file handle referenced by hWEBFS is already open.
+ Parameters: hWEBFS - the file handle from which to read the metadata
+ Returns: The size that was read as a uint32
+ ***************************************************************************/
+uint32 WEBFS_CODE_ATTR WEBFSGetSize(WEBFS_HANDLE hWEBFS)
+{
+ // Make sure a valid file is open
+ if(hWEBFS > MAX_WEBFS_OPENFILES || WEBFSStubs[hWEBFS].addr == WEBFS_INVALID)
+ return 0;
+
+ // Move to the point for reading
+ GetFATRecord(WEBFSStubs[hWEBFS].fatID);
+ return fatCache.len;
+}
+/*****************************************************************************
+ Function: uint32 WEBFSGetBytesRem(WEBFS_HANDLE hWEBFS)
+ Description: Determines how many uint8s remain to be read.
+ Precondition: The file handle referenced by hWEBFS is already open.
+ Parameters: hWEBFS - the file handle from which to read the metadata
+ Returns: The number of uint8s remaining in the file as a uint32
+ ***************************************************************************/
+uint32 WEBFS_CODE_ATTR WEBFSGetBytesRem(WEBFS_HANDLE hWEBFS)
+{
+ // Make sure a valid file is open
+ if(hWEBFS > MAX_WEBFS_OPENFILES || WEBFSStubs[hWEBFS].addr == WEBFS_INVALID)
+ return 0;
+ return WEBFSStubs[hWEBFS].bytesRem;
+}
+/*****************************************************************************
+ Function: WEBFS_PTR WEBFSGetStartAddr(WEBFS_HANDLE hWEBFS)
+ Description: Reads the starting address of a file.
+ Precondition: The file handle referenced by hWEBFS is already open.
+ Parameters: hWEBFS - the file handle from which to read the metadata
+ Returns: The starting address of the file in the WEBFS image
+ ***************************************************************************/
+WEBFS_PTR WEBFS_CODE_ATTR WEBFSGetStartAddr(WEBFS_HANDLE hWEBFS)
+{
+ // Make sure a valid file is open
+ if(hWEBFS > MAX_WEBFS_OPENFILES || WEBFSStubs[hWEBFS].addr == WEBFS_INVALID)
+ return 0;
+ // Move to the point for reading
+ GetFATRecord(WEBFSStubs[hWEBFS].fatID);
+ return fatCache.data;
+}
+/*****************************************************************************
+ Function: WEBFS_PTR WEBFSGetEndAddr(WEBFS_HANDLE hWEBFS)
+ Description: Determines the ending address of a file.
+ Precondition: The file handle referenced by hWEBFS is already open.
+ Parameters: hWEBFS - the file handle from which to read the metadata
+ Returns: The address just after the file ends (start address of next file)
+ ***************************************************************************/
+WEBFS_PTR WEBFS_CODE_ATTR WEBFSGetEndAddr(WEBFS_HANDLE hWEBFS)
+{
+ // Make sure a valid file is open
+ if(hWEBFS > MAX_WEBFS_OPENFILES || WEBFSStubs[hWEBFS].addr == WEBFS_INVALID)
+ return WEBFS_INVALID;
+ // Move to the point for reading
+ GetFATRecord(WEBFSStubs[hWEBFS].fatID);
+ return fatCache.data + fatCache.len;
+}
+/*****************************************************************************
+ Function: bool WEBFSGetFilename(WEBFS_HANDLE hWEBFS, uint8* cName, uint16 wLen)
+ Description: Reads the file name of a file that is already open.
+ Precondition: The file handle referenced by hWEBFS is already open.
+ Parameters:
+ hWEBFS - the file handle from which to determine the file name
+ cName - where to store the name of the file
+ wLen - the maximum length of data to store in cName
+ Returns:
+ true - the file name was successfully located
+ false - the file handle provided is not currently open
+ ***************************************************************************/
+bool WEBFS_CODE_ATTR WEBFSGetFilename(WEBFS_HANDLE hWEBFS, uint8* cName, uint16 wLen)
+{
+ uint32 addr;
+
+ // Make sure a valid file is open
+ if(hWEBFS > MAX_WEBFS_OPENFILES || WEBFSStubs[hWEBFS].addr == WEBFS_INVALID)
+ return false;
+
+ // Move to the point for reading
+ GetFATRecord(WEBFSStubs[hWEBFS].fatID);
+ addr = fatCache.string;
+ WEBFSStubs[0].addr = addr;
+ WEBFSStubs[0].bytesRem = 255;
+
+ // Read the value and return
+ WEBFSGetArray(0, cName, wLen);
+ return true;
+}
+/*****************************************************************************
+ Function: uint32 WEBFSGetPosition(WEBFS_HANDLE hWEBFS)
+ Description: Determines the current position in the file
+ Precondition: The file handle referenced by hWEBFS is already open.
+ Parameters: hWEBFS - the file handle for which to determine position
+ Returns: The position in the file as a uint32 (or WEBFS_PTR)
+ ***************************************************************************/
+uint32 WEBFS_CODE_ATTR WEBFSGetPosition(WEBFS_HANDLE hWEBFS)
+{
+ return WEBFSStubs[hWEBFS].addr - WEBFSGetStartAddr(hWEBFS);
+}
+/*****************************************************************************
+ Function: void WEBFS_Update(void)
+ Summary: Validates the WEBFS Image
+ Description: Verifies that the WEBFS image is valid, and reads the number of
+ available files from the image header. This function is called on
+ boot, and again after any image is written.
+ Parameters: None
+ Returns: None
+ ***************************************************************************/
+static void WEBFS_CODE_ATTR WEBFS_Update(void)
+{
+ // Update numFiles
+ WEBFS_DISK_HEADER dhead;
+ WEBFSStubs[0].addr = 0;
+ WEBFSStubs[0].bytesRem = sizeof(dhead);
+ WEBFSGetArray(0, (uint8*)&dhead, sizeof(dhead));
+ if(dhead.id == WEBFS_DISK_ID && dhead.ver == WEBFS_DISK_VER) { //"FWEB"1,0 ?
+ numFiles = dhead.numFiles;
+ }
+ else numFiles = 0;
+ fatCacheID = WEBFS_INVALID_FAT;
+}
+/****************************************************************************
+ * WEBFS_max_size()
+ ***************************************************************************/
+uint32 WEBFS_CODE_ATTR WEBFS_max_size(void)
+{
+/*
+ uint32 size = spi_flash_real_size();
+ if(size > WEBFS_DISK_ADDR_BIGFLASH) size -= WEBFS_DISK_ADDR_BIGFLASH;
+ else {
+ size = WEBFS_DISK_ADDR_MINFLASH_END - WEBFS_DISK_ADDR_MINFLASH_START;
+ }
+ return size;
+*/
+ return spi_flash_real_size() - WEBFS_DISK_FADDR;
+}
+/****************************************************************************
+ * WEBFS_size()
+ ***************************************************************************/
+uint32 WEBFS_CODE_ATTR WEBFS_curent_size(void)
+{
+ uint32 size = 0;
+ web_mutex_lock();
+ if(numFiles) flash_read_word(&flashobj, disk_base_addr + 8, (uint32_t *) &size);
+ web_mutex_unlock();
+ return size;
+}
+/****************************************************************************
+ * WEBFS_size()
+ ***************************************************************************/
+uint32 WEBFS_CODE_ATTR WEBFS_base_addr(void)
+{
+/*
+ uint32 webfs_faddr;
+ if(flash_get_size(&flashobj) <= WEBFS_DISK_ADDR_BIGFLASH) webfs_faddr = WEBFS_DISK_ADDR_MINFLASH_START;
+ else webfs_faddr = WEBFS_DISK_ADDR_BIGFLASH;
+ return webfs_faddr;
+*/
+ return WEBFS_DISK_FADDR;
+}
diff --git a/RTLGDB/Project/webfs/webfs.h b/RTLGDB/Project/webfs/webfs.h
new file mode 100644
index 0000000..d7c6c23
--- /dev/null
+++ b/RTLGDB/Project/webfs/webfs.h
@@ -0,0 +1,116 @@
+/*********************************************************************
+ *
+ * FileName: WEBFS.h
+ * Basis of MPFS2 (Microchip File System).
+ * WEBFS has its differences Based.
+ *
+ ********************************************************************/
+#ifndef __WEBFS1_H
+#define __WEBFS1_H
+
+#include "flash_eep.h"
+
+extern uint32 _irom0_text_end;
+
+#define WEBFS_DISK_FADDR 0x0D0000
+
+#define WEBFS_DISK_ID 0x42455746 // заголовок WEBFiles.bin
+#define WEBFS_DISK_VER 0x0001 // версия
+
+#define MAX_FILE_NAME_SIZE 64
+
+#ifndef MAX_WEBFS_OPENFILES
+ #define MAX_WEBFS_OPENFILES 31
+#endif
+
+ #define WEBFS_FLAG_ISZIPPED 0x0001 // Indicates a file is compressed with GZIP compression
+ #define WEBFS_FLAG_HASINDEX 0x0002 // Indicates a file has an associated index of dynamic variables
+ #define WEBFS_INVALID 0xffffffff // Indicates a position pointer is invalid
+ #define WEBFS_INVALID_FAT 0xffff // Indicates an invalid FAT cache
+ typedef uint32 WEBFS_PTR; // WEBFS Pointers are currently uint32s
+ typedef uint8 WEBFS_HANDLE; // WEBFS Handles are currently stored as uint8s
+ #define WEBFS_INVALID_HANDLE 0xff // Indicates that a handle is not valid
+
+
+ // Stores each file handle's information
+ // Handles are free when addr = WEBFS_INVALID
+ typedef struct
+ {
+ WEBFS_PTR addr; // Current address in the file system
+ uint32 bytesRem; // How many uint8s remain in this file
+#ifdef USE_MAX_IRAM
+ uint32 fatID; // ID of which file in the FAT was accessed
+#else
+ uint16 fatID; // ID of which file in the FAT was accessed
+#endif
+ } WEBFS_STUB;
+
+ // Indicates the method for WEBFSSeek
+ typedef enum
+ {
+ WEBFS_SEEK_START = 0, // Seek forwards from the front of the file
+ WEBFS_SEEK_END, // Seek backwards from the end of the file
+ WEBFS_SEEK_FORWARD, // Seek forward from the current position
+ WEBFS_SEEK_REWIND // See backwards from the current position
+ } WEBFS_SEEK_MODE;
+
+
+ typedef struct __attribute__((packed))
+ {
+ uint32 id;
+ uint16 ver;
+ uint16 numFiles;
+ uint32 disksize;
+ } WEBFS_DISK_HEADER ;
+
+ typedef struct __attribute__((packed))
+ {
+ uint32 blksize; // Length of file data - headlen
+ uint16 headlen; // headlen (Length of File Name + 0)
+ uint16 flags; // Flags for this file
+ } WEBFS_FHEADER;
+
+ // Stores the data for an WEBFS1 FAT record
+ typedef struct
+ {
+ uint32 string; // Pointer to the file name
+ uint32 data; // Address of the file data
+ uint32 len; // Length of file data
+#ifdef USE_MAX_IRAM
+ uint32 flags; // Flags for this file
+#else
+ uint16 flags; // Flags for this file
+#endif
+ } WEBFS_FAT_RECORD ;
+
+
+void WEBFSInit(void);
+WEBFS_HANDLE WEBFSOpen(uint8* cFile);
+void WEBFSClose(WEBFS_HANDLE hWEBFS);
+
+uint16 WEBFSGetArray(WEBFS_HANDLE hWEBFS, uint8* cData, uint16 wLen);
+
+uint16 WEBFSGetFlags(WEBFS_HANDLE hWEBFS);
+uint32 WEBFSGetSize(WEBFS_HANDLE hWEBFS);
+uint32 WEBFSGetBytesRem(WEBFS_HANDLE hWEBFS);
+WEBFS_PTR WEBFSGetStartAddr(WEBFS_HANDLE hWEBFS);
+WEBFS_PTR WEBFSGetEndAddr(WEBFS_HANDLE hWEBFS);
+bool WEBFSGetFilename(WEBFS_HANDLE hWEBFS, uint8* cName, uint16 wLen);
+uint32 WEBFSGetPosition(WEBFS_HANDLE hWEBFS);
+uint32 WEBFS_max_size(void);
+uint32 WEBFS_curent_size(void);
+uint32 WEBFS_base_addr(void);
+
+#ifdef USE_MAX_IRAM
+extern int isWEBFSLocked; // Lock WEBFS access during the upgrade
+extern uint32 numFiles;
+#else
+extern volatile bool isWEBFSLocked; // Lock WEBFS access during the upgrade
+extern uint16 numFiles;
+#endif
+
+extern WEBFS_FAT_RECORD fatCache;
+extern WEBFS_STUB WEBFSStubs[MAX_WEBFS_OPENFILES+1];
+extern uint32 disk_base_addr;
+
+#endif
diff --git a/RTLGDB/Project/wifi_user_set.h b/RTLGDB/Project/wifi_user_set.h
new file mode 100644
index 0000000..718cf48
--- /dev/null
+++ b/RTLGDB/Project/wifi_user_set.h
@@ -0,0 +1,78 @@
+/*
+ * wifi_user_set.h
+ *
+ * Created on: 01/04/2017
+ * Author: pvvx
+ */
+
+#ifndef _WIFI_USER_SET_H_
+#define _WIFI_USER_SET_H_
+
+// ====================================================================================================================================
+// ============================================ Wlan Config ===========================================================================
+#define DEF_WIFI_MODE RTW_MODE_STA // Стартовый режим WiFi: RTW_MODE_STA_AP, RTW_MODE_AP, RTW_MODE_STA, RTW_MODE_NONE
+#define DEF_WIFI_AP_STATIONS 3 // Max number of STAs, should be 1..3, default is 3
+#define DEF_WIFI_COUNTRY RTW_COUNTRY_RU // Регион использования WiFi...
+#define DEF_WIFI_TX_PWR RTW_TX_PWR_PERCENTAGE_12_5 // RTW_TX_PWR_PERCENTAGE_75 // RTW_TX_PWR_PERCENTAGE_100
+#define DEF_WIFI_BGN RTW_NETWORK_BGN // rtw_network_mode_t
+#define DEF_WIFI_ADAPTIVITY RTW_ADAPTIVITY_DISABLE // RTW_ADAPTIVITY_NORMAL // RTW_ADAPTIVITY_DISABLE/RTW_ADAPTIVITY_NORMAL/RTW_ADAPTIVITY_CARRIER_SENSE
+
+/* Опции загрузки конфигов по старту */
+//#define DEF_LOAD_CFG 0 // старт в назначенном режиме по умолчанию
+#define DEF_LOAD_CFG BID_ALL_WIFI_CFG // старт в назначенном общем режиме по умолчанию, с загрузками последних конфигураций ST и AP
+//#define DEF_LOAD_CFG (BID_ALL_WIFI_CFG | BID_WIFI_CFG) // старт в записанном режиме
+
+/* Опции разрешения записи конфигов по упсешному соединению или выполнению операции установок режимов WiFi без ошибок */
+#define DEF_SAVE_CFG (BID_ALL_WIFI_CFG | BID_WIFI_CFG) // сохранение по успешному соединению/выполненю для всех конфигов:
+ // (для ST или AP пишутся раздельно) с проверкой на изменения
+
+
+// ============================================ Interface 0 - wlan0 = AP =============================================================
+#define DEF_AP_SSID "PICH-18"
+#define DEF_AP_PASSWORD "0123456789"
+/* Варианты типов Security для AP:
+ RTW_SECURITY_OPEN - Open Security
+ RTW_SECURITY_WPA_TKIP_PSK - WPA Security
+ RTW_SECURITY_WPA2_AES_PSK - WPA2 Security using AES cipher
+ RTW_SECURITY_WPA2_MIXED_PSK - WPA2 Security using AES and/or TKIP ciphers */
+#define DEF_AP_SECURITY RTW_ENCRYPTION_WPA2_MIXED // WEP security is NOT IMPLEMENTED. It is NOT SECURE!
+#define DEF_AP_BEACON 100 // 100...6000 ms
+#define DEF_AP_CHANNEL 1 // 1..14
+#define DEF_AP_CHANNEL 1 // 1..14
+#define DEF_AP_DHCP_MODE 1 // =0 dhcp off, =1 - dhcp on
+#define DEF_AP_IP IP4ADDR(192,168,4,1)
+#define DEF_AP_MSK IP4ADDR(255,255,255,0)
+#define DEF_AP_GW IP4ADDR(192,168,4,1)
+// if not defined DHCP_START && DHCP_STOP -> 2..255
+//#define DEF_AP_DHCP_START 2 // DHCP ip start xx.xx.xx.2
+//#define DEF_AP_DHCP_STOP 15 // DHCP ip stop xx.xx.xx.15
+
+
+// ============================================ Interface 1 - wlan1 = STA =============================================================
+#define DEF_ST_SSID "APNAME" // РРјСЏ SSID AP (роутера) для присоединения РїРѕ умолчанию (первый старт)
+#define DEF_ST_PASSWORD "1234567890" // Пароль AP (роутера) для присоединения по умолчанию (первый старт)
+#define DEF_ST_SECURITY RTW_ENCRYPTION_WPA2_MIXED // РўРёРї Security
+#define DEF_ST_BSSID { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } // If bssid set is not ff.ff.ff.ff.ff.ff,
+#define DEF_ST_USE_BSSID 0 // station will connect to the router with both ssid[] and bssid[] matched.
+#define DEF_ST_CHANNEL 1 // 1..14
+#define DEF_ST_AUTORECONNECT 1 // 0 - none, 1..254 - count, 255 - all
+#define DEF_ST_RECONNECT_PAUSE 1 // 5 sec
+#define DEF_ST_SLEEP 3 // 0 - Off, 1 - IPS, 2 - LPS, 3 - IPS/LPS mode
+#define DEF_ST_LPS_DTIM 1 // LPS DTIM
+#define DEF_ST_DHCP_MODE 1 // =0 dhcp off,
+ // =1 - dhcp on, - динамический ip
+ // =2 Static ip, - fixed ip
+ // =3 - auto fix - старт в режиме "dhcp on", после получения ip - фиксация и переключение в режим рестартов со "Static ip"
+#define DEF_ST_IP IP4ADDR(192,168,1,100)
+#define DEF_ST_MSK IP4ADDR(255,255,255,0)
+#define DEF_ST_GW IP4ADDR(192,168,1,1)
+
+// ============================================ Interface 2 - eth0 =============================================================
+
+#define DEF_EH_DHCP_MODE 1 // =0 dhcp off, =1 - dhcp on
+#define DEF_EH_IP IP4ADDR(192,168,7,200)
+#define DEF_EH_MSK IP4ADDR(255,255,255,0)
+#define DEF_EH_GW IP4ADDR(192,168,7,1)
+
+
+#endif /* _WIFI_USER_SET_H_ */
diff --git a/RTLGDB/RTLGDB.vcxproj b/RTLGDB/RTLGDB.vcxproj
new file mode 100644
index 0000000..49216c0
--- /dev/null
+++ b/RTLGDB/RTLGDB.vcxproj
@@ -0,0 +1,660 @@
+п»ї
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ LinuxDebugger
+ ssh
+ gdb
+ gdb
+ localhost:3333
+ IoT
+ {3D8B16B6-9763-48AD-A514-F45680E8613B}
+
+
+
+ Makefile
+ true
+ v140
+
+
+ Makefile
+ false
+ v140
+
+
+ Makefile
+ true
+ v140
+
+
+ Makefile
+ false
+ v140
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+ false
+ <_ApplicableDebuggers>Desktop
+ LinuxDebugger
+
+
+
+
+
+
+
+
+
+
+
+ Project
+
+
+
+ PropertySheet
+
+
+
+ File
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ mingw32-make -s -j 6 all
+ C:\RTL\6-2017-q2\arm-none-eabi\include;$(ProjectDir)USDK\component\common\mbed\targets\hal\rtl8195a;$(ProjectDir)USDK\component\common\mbed\common;$(ProjectDir)USDK\component\common\mbed\hal;$(ProjectDir)USDK\component\common\mbed\hal_ext;$(ProjectDir)USDK\component\common\mbed\api;$(ProjectDir)USDK\component\common\api;$(ProjectDir)USDK\component\common\api\at_cmd;$(ProjectDir)USDK\component\common\api\network;$(ProjectDir)USDK\component\common\api\platform;$(ProjectDir)USDK\component\common\api\wifi\rtw_wowlan;$(ProjectDir)USDK\component\common\api\wifi;$(ProjectDir)USDK\component\common\network;$(ProjectDir)USDK\component\common\network\lwip\port\realtek;$(ProjectDir)USDK\component\common\network\lwip\port\realtek\arch;$(ProjectDir)USDK\component\common\network\lwip\port\realtek\freertos;$(ProjectDir)USDK\component\common\network\lwip\src\api;$(ProjectDir)USDK\component\common\network\lwip\src\core\ipv4;$(ProjectDir)USDK\component\common\network\lwip\src\core\snmp;$(ProjectDir)USDK\component\common\network\lwip\src\core;$(ProjectDir)USDK\component\common\network\lwip\src\include;$(ProjectDir)USDK\component\common\network\lwip\src\include\ipv4;$(ProjectDir)USDK\component\common\network\lwip\src\include\ipv4\lwip;$(ProjectDir)USDK\component\common\network\lwip\src\include\lwip;$(ProjectDir)USDK\component\common\network\lwip\src\include\netif;$(ProjectDir)USDK\component\common\network\lwip\src\include\posix\sys;$(ProjectDir)USDK\component\common\network\lwip\src\include\posix;$(ProjectDir)USDK\component\common\network\lwip\src\netif;$(ProjectDir)USDK\component\common\drivers\wlan\realtek\include;$(ProjectDir)USDK\component\common\drivers\wlan\realtek\include\byteorder;$(ProjectDir)USDK\component\common\drivers\wlan\realtek\src\osdep;$(ProjectDir)USDK\component\common\drivers\wlan\realtek\src\osdep\freertos;$(ProjectDir)USDK\component\os\freertos\freertos\Source;$(ProjectDir)USDK\component\os\freertos\freertos\Source\portable\GCC\ARM_CM3;$(ProjectDir)USDK\component\os\freertos\freertos\Source\include;$(ProjectDir)USDK\component\os\freertos;$(ProjectDir)USDK\component\os\os_dep\include;$(ProjectDir)USDK\component\os\os_dep;$(ProjectDir)USDK\component\os\rtx;$(ProjectDir)USDK\component\soc\realtek\common\bsp;$(ProjectDir)USDK\component\soc\realtek\8195a\fwlib;$(ProjectDir)USDK\component\soc\realtek\8195a\fwlib\src;$(ProjectDir)USDK\component\soc\realtek\8195a\fwlib\rtl8195a;$(ProjectDir)USDK\component\soc\realtek\8195a\fwlib\rtl8195a\src;$(ProjectDir)USDK\component\soc\realtek\8195a\fwlib\ram_lib;$(ProjectDir)USDK\component\soc\realtek\8195a\fwlib\ram_lib\wlan\realtek\wlan_ram_map\rom;$(ProjectDir)USDK\component\soc\realtek\8195a\fwlib\ram_lib\usb_otg\include;$(ProjectDir)USDK\component\soc\realtek\8195a\fwlib\ram_lib\usb_otg\include\usb_otg_inc;$(ProjectDir)USDK\component\soc\realtek\8195a\cmsis;$(ProjectDir)USDK\component\soc\realtek\8195a\cmsis\device;$(ProjectDir)USDK\component\soc\realtek\8195a\misc\driver;$(ProjectDir)USDK\component\soc\realtek\8195a\misc\platform;$(ProjectDir)USDK\component\soc\realtek\8195a\misc\os;$(ProjectDir)USDK\component\soc\realtek\8195a\misc\rtl_std_lib;$(ProjectDir)USDK\component\soc\realtek\8195a\misc\rtl_std_lib\include;$(ProjectDir)USDK\component\soc\realtek\8195a\misc\rtl_std_lib\lib_rtlstd;$(ProjectDir)USDK\component\soc\realtek\8195a\misc\rtl_std_lib\libc\rom\string;$(ProjectDir)USDK\component\soc\realtek\8195a\misc\rtl_std_lib\libgloss\rtl8195a\rom;$(ProjectDir)Project;$(ProjectDir)Project\web;$(ProjectDir)Project\webfs;$(ProjectDir)Project\tcpsrv;$(ProjectDir)Project\driver;$(ProjectDir)Project\rtl8195a;$(ProjectDir)Project\ina219;$(ProjectDir)Project\adc_ws;$(ProjectDir)Project\MPU6050;$(ProjectDir)Project\SSD1306;$(ProjectDir)Project\MLX90614;$(ProjectDir)Project\WS2812;$(IncludePath)
+ mingw32-make -s -j 6 rebuild
+ mingw32-make -s clean
+ ram_all.bin
+ $(ProjectDir)Debug\bin\
+ $(ProjectDir)Debug
+ CONFIG_PLATFORM_8195A=1;GCC_ARMCM3;M3;F_CPU=166666666L;__STDC__;__extension__=
+ $(PATH)
+
+
+
+
+
+ $(SourcePath)
+
+
+
+
+
+
+
+ $(ProjectDir)Debug\$(MSBuildProjectName).log
+
+
+
+
+
\ No newline at end of file
diff --git a/RTLGDB/RTLGDB.vcxproj.filters b/RTLGDB/RTLGDB.vcxproj.filters
new file mode 100644
index 0000000..29f3178
--- /dev/null
+++ b/RTLGDB/RTLGDB.vcxproj.filters
@@ -0,0 +1,1794 @@
+п»ї
+
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+
+
+
+
+ USDK
+
+
+ USDK
+
+
+ USDK
+
+
+ USDK
+
+
+ USDK
+
+
+ WEBFiles
+
+
+ WEBFiles
+
+
+ WEBFiles
+
+
+ WEBFiles
+
+
+ WEBFiles
+
+
+ WEBFiles
+
+
+ WEBFiles
+
+
+ WEBFiles
+
+
+ WEBFiles
+
+
+ WEBFiles
+
+
+ WEBFiles
+
+
+ WEBFiles
+
+
+ WEBFiles
+
+
+ WEBFiles
+
+
+
+
+ {08a26e93-524c-4982-a01c-c8d4f223d6be}
+
+
+ {af4e8ee4-e406-4847-a22e-226417025f10}
+
+
+ {ecd0e7a7-531f-4217-a881-e1e0eb621fab}
+
+
+ {5288d335-429c-479a-87f4-5d501fa5f607}
+
+
+ {72e8ee11-444a-45bf-ae91-086a758d2618}
+
+
+ {b014e9e9-13dd-4945-aa54-d3cbe961df2b}
+
+
+ {bdc045f1-676a-4c2e-98dc-4c7011a097f5}
+
+
+ {2602ad5c-5b75-46cc-8329-75dbd58ceba3}
+
+
+ {50d960d6-c301-402f-ad1c-33d14b7a4dbd}
+
+
+ {d2dbf689-f27b-4505-913b-edfefef7eb67}
+
+
+ {d8f42812-c46b-48c5-9d7f-ee1bfbba4b87}
+
+
+ {1bb167b0-34a3-4b65-9cea-4cbed30dd4bb}
+
+
+ {016841a5-3b07-4f94-bb12-b31883d45b49}
+
+
+ {78f72bec-3f46-43e4-a7a1-a945df2bca74}
+
+
+ {a87a2ceb-e33a-4a05-bb2c-9812e68d9640}
+
+
+ {8910a041-f880-43bf-9bef-f14c2ab51a5d}
+
+
+ {b034088a-75c9-4eed-b4f5-29a45c21ce71}
+
+
+ {a50b9c26-7062-4bb6-abb2-3f112109d17c}
+
+
+ {7e58d994-4bfa-42b6-97c4-b491b3ebda8e}
+
+
+ {55db239c-cc9d-4fc0-980d-4c81373269b2}
+
+
+ {d5cb2f53-86df-4d9c-b49a-ff27c82bb756}
+
+
+ {33e076dd-aa6a-4025-b780-30ee285680c4}
+
+
+ {f3ed6348-e1f5-470b-8570-f29bdb6638c2}
+
+
+ {b0e18d25-33c7-4e1d-bc56-a1260280b139}
+
+
+ {8c95d98e-afb1-4f5c-a14d-91cb4763d782}
+
+
+ {096ebc40-6894-49fd-8b52-04322f6591c3}
+
+
+ {e6d18fba-43bb-41df-a93a-1d993a4a267d}
+
+
+ {01fadd8c-9e93-40cd-9efb-72646df020c6}
+
+
+ {a0096c24-5171-4864-b77e-4f0a34e6976c}
+
+
+ {0f60cfc0-438c-4d04-91f4-cb0847341608}
+
+
+ {c37ac131-62ee-451a-a2bf-414fd9304c75}
+
+
+ {94b7e724-6ae2-43b7-8058-102cec0b72c0}
+
+
+ {fd5b466a-a5f4-40a7-87ed-5de226fcbde7}
+
+
+ {96d3130f-cc4f-44ae-91dd-1c5869ab4c79}
+
+
+ {15863588-146b-40b1-a2c0-6791fe6992d7}
+
+
+ {829362c2-bc6d-4481-a282-dbb5b0974c6f}
+
+
+ {e1a517b9-9564-4a08-98c7-5ce47f55bfb8}
+
+
+ {d3dc3239-caff-4b38-ba23-3d33417a7427}
+
+
+ {63d64419-2c07-4426-80b7-59f108d94e42}
+
+
+ {76e3b46c-b00b-4aed-a790-e8095891ac47}
+
+
+ {b2673331-9227-431b-bf26-f3950f9fc61f}
+
+
+ {e142b148-8d5d-456c-817e-11a395464e3e}
+
+
+ {8f812468-9d50-4c08-97fa-f95595242d6d}
+
+
+ {cd792418-8a24-42ee-b501-4cd7de08d655}
+
+
+ {b83832e1-25ce-4c21-a70e-6e36d93023c2}
+
+
+ {904a78a5-f412-476c-991d-27026a35030b}
+
+
+ {50bddb50-3ba7-4b4d-98af-93e719d0560b}
+
+
+ {a06dcc19-509e-431a-9f53-eb7417fed78a}
+
+
+ {5d1454d4-bf49-4d6c-becf-edf7c9b46f88}
+
+
+ {4159f405-9a9c-4471-aae5-0e39825a123c}
+
+
+ {4f9f22b5-2357-4bae-92e9-71f5833e915c}
+
+
+ {03be9a0c-e2e3-4fd5-9cc6-322f6920bd66}
+
+
+ {fc66df77-bf94-4290-8bee-4cfe01edfbbd}
+
+
+ {ec299e57-688c-4952-a59d-0066e9d9b828}
+
+
+ {3b95f927-1b9c-4deb-9a43-ef17ff580860}
+
+
+ {466c00ee-e82a-43a0-bde7-6303df1b8b3b}
+
+
+ {c54fe2ff-adf0-4ead-8ea6-7597d73a8f21}
+
+
+ {5f23425b-07ba-4da3-82fb-01389f9d6823}
+
+
+ {7efca65d-2fc2-4847-932e-884eaf3b0d1e}
+
+
+ {aef44d77-3518-4be9-8189-8b2ca6259264}
+
+
+ {4e680784-982e-4ee9-b999-e3980683875e}
+
+
+ {e335d202-d022-4a2e-9e21-5fd70e47ed4b}
+
+
+ {a30614c9-e68c-48bc-bae7-32bafe027f51}
+
+
+ {029b1e98-955f-44a0-b534-65a8b6617e0d}
+
+
+ {b408a7c8-8f6c-4300-b684-b6708e3a757d}
+
+
+ {b504c8a2-ad3c-484e-b3c3-9d26727f1d47}
+
+
+ {85a1adff-4f54-4722-9926-a11c12b07630}
+
+
+ {bbc2cfef-d508-4ce2-b4eb-e5ecd2820376}
+
+
+ {98131a92-9304-4820-8f5f-ac8dffd0dab3}
+
+
+ {0d9c4a2e-1df0-4ac7-973c-3747bcad49f7}
+
+
+ {a3667ce5-8a45-4d37-8a74-3d7baa58d9f3}
+
+
+ {0b6a769a-b849-4622-a163-43d3e4ba2a92}
+
+
+ {ba72b723-d707-4885-9d7e-e81dd91968c9}
+
+
+ {688c838e-5b2d-4240-9f38-2c36f58c864a}
+
+
+ {408f5db7-69fd-4fea-a77a-7a43597f7ccd}
+
+
+ {c71f79cb-3925-4614-aadb-ebc75d56b204}
+
+
+ {e5b26651-f2f5-454e-8c02-9ed742519e3f}
+
+
+ {272a6c70-71b2-4ad5-b065-efd7b0eb90ef}
+
+
+ {c23138eb-23eb-41b0-88b9-bfd6578d2eca}
+
+
+ {bd2cf493-28ea-4ebb-ba05-fc5323ebb11a}
+
+
+
+
+ Project
+
+
+ Project
+
+
+ Project
+
+
+ Project
+
+
+ Project
+
+
+ Project
+
+
+ Project
+
+
+ Project
+
+
+ Project
+
+
+ Project
+
+
+ Project\webfs
+
+
+ Project\rtl8195a
+
+
+ Project\rtl8195a
+
+
+ Project\rtl8195a
+
+
+ Project\rtl8195a
+
+
+ Project\rtl8195a
+
+
+ Project\rtl8195a
+
+
+ Project\tcpsrv
+
+
+ Project\web
+
+
+ Project\web
+
+
+ Project\web
+
+
+ Project\web
+
+
+ Project\web
+
+
+ Project\driver
+
+
+ Project\driver
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ Project\ina219
+
+
+ Project\ina219
+
+
+ Project\ina219
+
+
+ USDK\component\common\mbed\hal
+
+
+ USDK\component\common\mbed\hal
+
+
+ USDK\component\common\mbed\hal
+
+
+ USDK\component\common\mbed\hal
+
+
+ USDK\component\common\mbed\hal
+
+
+ USDK\component\common\mbed\hal
+
+
+ USDK\component\common\mbed\hal
+
+
+ USDK\component\common\mbed\hal
+
+
+ USDK\component\common\mbed\hal
+
+
+ USDK\component\common\mbed\hal
+
+
+ USDK\component\common\mbed\hal
+
+
+ USDK\component\common\mbed\hal
+
+
+ USDK\component\common\mbed\hal
+
+
+ USDK\component\common\mbed\hal
+
+
+ USDK\component\common\mbed\hal
+
+
+ USDK\component\soc\realtek\8195a\cmsis\device
+
+
+ USDK\component\soc\realtek\8195a\cmsis\device
+
+
+ USDK\component\soc\realtek\8195a\cmsis\device
+
+
+ USDK\component\soc\realtek\8195a\cmsis\device
+
+
+ USDK\component\soc\realtek\8195a\cmsis\device
+
+
+ USDK\component\soc\realtek\8195a\cmsis\device
+
+
+ USDK\component\soc\realtek\8195a\cmsis\device
+
+
+ USDK\component\soc\realtek\8195a\cmsis\device
+
+
+ USDK\component\soc\realtek\8195a\cmsis\device
+
+
+ USDK\component\common\mbed\targets\hal\rtl8195a
+
+
+ USDK\component\common\mbed\targets\hal\rtl8195a
+
+
+ USDK\component\common\mbed\targets\hal\rtl8195a
+
+
+ USDK\component\common\mbed\targets\hal\rtl8195a
+
+
+ USDK\component\common\mbed\targets\hal\rtl8195a
+
+
+ USDK\component\common\mbed\targets\hal\rtl8195a
+
+
+ USDK\component\common\mbed\targets\hal\rtl8195a
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\include
+
+
+ USDK\component\common\drivers\wlan\realtek\src\osdep\freertos
+
+
+ USDK\component\common\drivers\wlan\realtek\src\osdep\freertos
+
+
+ USDK\component\common\drivers\wlan\realtek\src\osdep\freertos
+
+
+ USDK\component\common\drivers\wlan\realtek\src\osdep\freertos
+
+
+ USDK\component\common\drivers\wlan\realtek\src\osdep\freertos
+
+
+ USDK\component\common\drivers\wlan\realtek\src\osdep
+
+
+ USDK\component\common\drivers\wlan\realtek\src\osdep
+
+
+ USDK\component\common\drivers\wlan\realtek\src\osdep
+
+
+ USDK\component\common\drivers\wlan\realtek\src\osdep
+
+
+ USDK\component\common\drivers\wlan\realtek\src\osdep
+
+
+ USDK\component\common\drivers\wlan\realtek\src\osdep
+
+
+ USDK\component\soc\realtek\8195a\misc\rtl_std_lib\include
+
+
+ USDK\component\soc\realtek\8195a\misc\rtl_std_lib\include
+
+
+ USDK\component\soc\realtek\8195a\misc\rtl_std_lib\include
+
+
+ USDK\component\soc\realtek\8195a\misc\rtl_std_lib\include
+
+
+ USDK\component\common\mbed\hal_ext
+
+
+ USDK\component\common\mbed\hal_ext
+
+
+ USDK\component\common\mbed\hal_ext
+
+
+ USDK\component\common\mbed\hal_ext
+
+
+ USDK\component\common\mbed\hal_ext
+
+
+ USDK\component\common\mbed\hal_ext
+
+
+ USDK\component\common\mbed\hal_ext
+
+
+ USDK\component\common\mbed\hal_ext
+
+
+ USDK\component\common\mbed\hal_ext
+
+
+ USDK\component\common\mbed\hal_ext
+
+
+ USDK\component\common\mbed\hal_ext
+
+
+ USDK\component\common\mbed\hal_ext
+
+
+ USDK\component\common\mbed\hal_ext
+
+
+ USDK\component\common\mbed\hal_ext
+
+
+ USDK\component\common\mbed\hal_ext
+
+
+ USDK\component\common\mbed\hal_ext
+
+
+ USDK\component\common\mbed\hal_ext
+
+
+ USDK\component\common\mbed\hal_ext
+
+
+ USDK\component\os\freertos
+
+
+ USDK\component\os\os_dep\include
+
+
+ USDK\component\os\os_dep\include
+
+
+ USDK\component\os\os_dep\include
+
+
+ USDK\component\os\os_dep\include
+
+
+ USDK\component\soc\realtek\8195a\misc\os
+
+
+ USDK\component\soc\realtek\8195a\misc\os
+
+
+ USDK\component\soc\realtek\8195a\misc\os
+
+
+ USDK\component\soc\realtek\8195a\misc\os
+
+
+ USDK\component\soc\realtek\8195a\misc\os
+
+
+ USDK\component\common\api\wifi
+
+
+ USDK\component\common\api\wifi
+
+
+ USDK\component\common\api\wifi
+
+
+ USDK\component\common\api\wifi
+
+
+ USDK\component\common\api\wifi
+
+
+ USDK\component\common\api\wifi\rtw_wowlan
+
+
+ USDK\component\common\api
+
+
+ USDK\component\common\api
+
+
+ USDK\component\common\api
+
+
+ USDK\component\common\api
+
+
+ USDK\component\common\drivers\wlan\realtek\src\hci\lxbus
+
+
+ USDK\component\common\drivers\wlan\realtek\src\hci
+
+
+ USDK\component\common\drivers\wlan\realtek\src\hci
+
+
+ USDK\component\common\drivers\wlan\realtek\src\hci\gspi
+
+
+ USDK\component\common\drivers\wlan\realtek\src\hci\sdio
+
+
+ USDK\component\soc\realtek\8195a\misc\driver
+
+
+ USDK\component\soc\realtek\8195a\misc\driver
+
+
+ USDK\component\common\api\wifi\rtw_wpa_supplicant\src\utils\rom
+
+
+ USDK\component\common\api\wifi\rtw_wpa_supplicant\src\utils
+
+
+ USDK\component\common\api\wifi\rtw_wpa_supplicant\src\wps
+
+
+ Project\MPU6050
+
+
+ USDK\component\soc\realtek\common\bsp
+
+
+ USDK\component\soc\realtek\common\bsp
+
+
+ Project
+
+
+ Project
+
+
+ Project\WS2812
+
+
+ Project\MPU6050
+
+
+ USDK\component\common\drivers\wlan\realtek\include\byteorder
+
+
+ USDK\component\common\drivers\wlan\realtek\include\byteorder
+
+
+ USDK\component\common\drivers\wlan\realtek\include\byteorder
+
+
+ USDK\component\common\network\lwip\src\include\ipv4\lwip
+
+
+ USDK\component\common\network\lwip\src\include\ipv4\lwip
+
+
+ USDK\component\common\network\lwip\src\include\ipv4\lwip
+
+
+ USDK\component\common\network\lwip\src\include\ipv4\lwip
+
+
+ USDK\component\common\network\lwip\src\include\ipv4\lwip
+
+
+ USDK\component\common\network\lwip\src\include\ipv4\lwip
+
+
+ USDK\component\common\network\lwip\src\include\ipv4\lwip
+
+
+ USDK\component\common\network\lwip\src\include\ipv4\lwip
+
+
+ USDK\component\common\network\lwip\src\include\lwip
+
+
+ USDK\component\common\network\lwip\src\include\lwip
+
+
+ USDK\component\common\network\lwip\src\include\lwip
+
+
+ USDK\component\common\network\lwip\src\include\lwip
+
+
+ USDK\component\common\network\lwip\src\include\lwip
+
+
+ USDK\component\common\network\lwip\src\include\lwip
+
+
+ USDK\component\common\network\lwip\src\include\lwip
+
+
+ USDK\component\common\network\lwip\src\include\lwip
+
+
+ USDK\component\common\network\lwip\src\include\lwip
+
+
+ USDK\component\common\network\lwip\src\include\lwip
+
+
+ USDK\component\common\network\lwip\src\include\lwip
+
+
+ USDK\component\common\network\lwip\src\include\lwip
+
+
+ USDK\component\common\network\lwip\src\include\lwip
+
+
+ USDK\component\common\network\lwip\src\include\lwip
+
+
+ USDK\component\common\network\lwip\src\include\lwip
+
+
+ USDK\component\common\network\lwip\src\include\lwip
+
+
+ USDK\component\common\network\lwip\src\include\lwip
+
+
+ USDK\component\common\network\lwip\src\include\lwip
+
+
+ USDK\component\common\network\lwip\src\include\lwip
+
+
+ USDK\component\common\network\lwip\src\include\lwip
+
+
+ USDK\component\common\network\lwip\src\include\lwip
+
+
+ USDK\component\common\network\lwip\src\include\lwip
+
+
+ USDK\component\common\network\lwip\src\include\lwip
+
+
+ USDK\component\common\network\lwip\src\include\lwip
+
+
+ USDK\component\common\network\lwip\src\include\lwip
+
+
+ USDK\component\common\network\lwip\src\include\lwip
+
+
+ USDK\component\common\network\lwip\src\include\lwip
+
+
+ USDK\component\common\network\lwip\src\include\lwip
+
+
+ USDK\component\common\network\lwip\src\include\lwip
+
+
+ USDK\component\common\network\lwip\src\include\lwip
+
+
+ USDK\component\common\network\lwip\src\include\lwip
+
+
+ USDK\component\common\network\lwip\src\include\lwip
+
+
+ USDK\component\common\network\lwip\src\include\netif
+
+
+ USDK\component\common\network\lwip\src\include\netif
+
+
+ USDK\component\common\network\lwip\src\include\netif
+
+
+ USDK\component\common\network\lwip\src\include\netif
+
+
+ USDK\component\common\network\lwip\src\include\posix
+
+
+ USDK\component\common\network\lwip\src\include\posix\sys
+
+
+ USDK\component\common\network\lwip\port\realtek\freertos
+
+
+ USDK\component\common\network\lwip\port\realtek\freertos
+
+
+
+
+ Project
+
+
+ Project
+
+
+ Project\webfs
+
+
+ Project\tcpsrv
+
+
+ Project\web
+
+
+ Project\web
+
+
+ Project\web
+
+
+ Project\web
+
+
+ Project\web
+
+
+ Project\web
+
+
+ Project\web
+
+
+ Project\driver
+
+
+ Project\driver
+
+
+ Project\console
+
+
+ Project\console
+
+
+ Project\console
+
+
+ Project\console
+
+
+ Project\console
+
+
+ Project\console
+
+
+ Project\console
+
+
+ Project\console
+
+
+ Project\console
+
+
+ Project\console
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ USDK\component\soc\realtek\8195a\fwlib\rtl8195a
+
+
+ Project\ina219
+
+
+ Project\ina219
+
+
+ USDK\component\soc\realtek\8195a\cmsis\device
+
+
+ USDK\component\soc\realtek\8195a\cmsis\device
+
+
+ USDK\component\soc\realtek\8195a\cmsis\device
+
+
+ USDK\component\common\mbed\targets\hal\rtl8195a
+
+
+ USDK\component\common\mbed\targets\hal\rtl8195a
+
+
+ USDK\component\common\mbed\targets\hal\rtl8195a
+
+
+ USDK\component\common\mbed\targets\hal\rtl8195a
+
+
+ USDK\component\common\mbed\targets\hal\rtl8195a
+
+
+ USDK\component\common\mbed\targets\hal\rtl8195a
+
+
+ USDK\component\common\mbed\targets\hal\rtl8195a
+
+
+ USDK\component\common\mbed\targets\hal\rtl8195a
+
+
+ USDK\component\common\mbed\targets\hal\rtl8195a
+
+
+ USDK\component\common\mbed\targets\hal\rtl8195a
+
+
+ USDK\component\common\mbed\targets\hal\rtl8195a
+
+
+ USDK\component\common\mbed\targets\hal\rtl8195a
+
+
+ USDK\component\common\mbed\targets\hal\rtl8195a
+
+
+ USDK\component\common\mbed\targets\hal\rtl8195a
+
+
+ USDK\component\common\mbed\targets\hal\rtl8195a
+
+
+ USDK\component\common\mbed\targets\hal\rtl8195a
+
+
+ USDK\component\common\mbed\targets\hal\rtl8195a
+
+
+ USDK\component\common\mbed\targets\hal\rtl8195a
+
+
+ USDK\component\common\mbed\targets\hal\rtl8195a
+
+
+ USDK\component\common\mbed\targets\hal\rtl8195a
+
+
+ USDK\component\common\mbed\targets\hal\rtl8195a
+
+
+ USDK\component\common\mbed\targets\hal\rtl8195a
+
+
+ USDK\component\common\mbed\targets\hal\rtl8195a
+
+
+ USDK\component\common\mbed\targets\hal\rtl8195a
+
+
+ USDK\component\common\mbed\targets\hal\rtl8195a
+
+
+ USDK\component\common\drivers\wlan\realtek\src\osdep
+
+
+ USDK\component\os\freertos
+
+
+ USDK\component\os\os_dep
+
+
+ USDK\component\os\os_dep
+
+
+ USDK\component\os\os_dep
+
+
+ USDK\component\soc\realtek\8195a\misc\os
+
+
+ USDK\component\soc\realtek\8195a\misc\os
+
+
+ USDK\component\soc\realtek\8195a\misc\os
+
+
+ USDK\component\common\api\wifi
+
+
+ USDK\component\common\api\wifi
+
+
+ USDK\component\common\api\wifi
+
+
+ USDK\component\common\api\wifi
+
+
+ USDK\component\common\api\wifi
+
+
+ USDK\component\common\api\wifi\rtw_wowlan
+
+
+ USDK\component\common\api\wifi\rtw_wpa_supplicant\wpa_supplicant
+
+
+ USDK\component\common\api\wifi\rtw_wpa_supplicant\wpa_supplicant
+
+
+ USDK\component\common\api\wifi\rtw_wpa_supplicant\wpa_supplicant
+
+
+ USDK\component\common\api
+
+
+ USDK\component\common\api
+
+
+ USDK\component\common\api
+
+
+ USDK\component\common\api
+
+
+ USDK\component\common\api
+
+
+ USDK\component\common\drivers\wlan\realtek\src\hci\gspi
+
+
+ USDK\component\common\drivers\wlan\realtek\src\hci\gspi
+
+
+ USDK\component\common\drivers\wlan\realtek\src\hci\gspi
+
+
+ USDK\component\common\drivers\wlan\realtek\src\hci\sdio
+
+
+ USDK\component\common\drivers\wlan\realtek\src\hci\sdio
+
+
+ USDK\component\common\drivers\wlan\realtek\src\hci\sdio
+
+
+ USDK\component\soc\realtek\8195a\misc\driver
+
+
+ USDK\component\soc\realtek\8195a\misc\driver
+
+
+ USDK\component\soc\realtek\8195a\misc\driver
+
+
+ USDK\component\soc\realtek\8195a\misc\driver
+
+
+ USDK\component\soc\realtek\8195a\misc\driver
+
+
+ USDK\component\soc\realtek\8195a\fwlib\ram_lib
+
+
+ USDK\component\soc\realtek\8195a\fwlib\ram_lib
+
+
+ USDK\component\soc\realtek\8195a\fwlib\ram_lib
+
+
+ USDK\component\soc\realtek\8195a\fwlib\ram_lib
+
+
+ USDK\component\soc\realtek\8195a\fwlib\ram_lib
+
+
+ USDK\component\soc\realtek\8195a\fwlib\ram_lib
+
+
+ USDK\component\soc\realtek\8195a\fwlib\ram_lib
+
+
+ USDK\component\soc\realtek\8195a\fwlib\ram_lib
+
+
+ USDK\component\soc\realtek\8195a\fwlib\ram_lib
+
+
+ USDK\component\soc\realtek\8195a\fwlib\ram_lib
+
+
+ USDK\component\common\api\wifi\rtw_wpa_supplicant\src\utils
+
+
+ USDK\component\soc\realtek\8195a\misc\rtl_std_lib\lib_rtlstd
+
+
+ USDK\component\soc\realtek\8195a\misc\rtl_std_lib\lib_rtlstd
+
+
+ USDK\component\soc\realtek\8195a\misc\rtl_std_lib\lib_rtlstd
+
+
+ USDK\component\soc\realtek\8195a\misc\rtl_std_lib\lib_rtlstd
+
+
+ USDK\component\soc\realtek\8195a\misc\rtl_std_lib\lib_rtlstd
+
+
+ USDK\component\soc\realtek\8195a\misc\rtl_std_lib\lib_rtlstd
+
+
+ Project\MPU6050
+
+
+ Project
+
+
+ Project
+
+
+ Project\WS2812
+
+
+ Project\MPU6050
+
+
+ USDK\component\common\network\lwip\src\api
+
+
+ USDK\component\common\network\lwip\src\api
+
+
+ USDK\component\common\network\lwip\src\api
+
+
+ USDK\component\common\network\lwip\src\api
+
+
+ USDK\component\common\network\lwip\src\api
+
+
+ USDK\component\common\network\lwip\src\api
+
+
+ USDK\component\common\network\lwip\src\api
+
+
+ USDK\component\common\network\lwip\src\api
+
+
+ USDK\component\common\network\lwip\src\netif
+
+
+ USDK\component\common\network\lwip\src\core
+
+
+ USDK\component\common\network\lwip\src\core
+
+
+ USDK\component\common\network\lwip\src\core
+
+
+ USDK\component\common\network\lwip\src\core
+
+
+ USDK\component\common\network\lwip\src\core
+
+
+ USDK\component\common\network\lwip\src\core
+
+
+ USDK\component\common\network\lwip\src\core
+
+
+ USDK\component\common\network\lwip\src\core
+
+
+ USDK\component\common\network\lwip\src\core
+
+
+ USDK\component\common\network\lwip\src\core
+
+
+ USDK\component\common\network\lwip\src\core
+
+
+ USDK\component\common\network\lwip\src\core
+
+
+ USDK\component\common\network\lwip\src\core
+
+
+ USDK\component\common\network\lwip\src\core
+
+
+ USDK\component\common\network\lwip\src\core
+
+
+ USDK\component\common\network\lwip\src\core
+
+
+ USDK\component\common\network\lwip\src\core\snmp
+
+
+ USDK\component\common\network\lwip\src\core\snmp
+
+
+ USDK\component\common\network\lwip\src\core\snmp
+
+
+ USDK\component\common\network\lwip\src\core\snmp
+
+
+ USDK\component\common\network\lwip\src\core\snmp
+
+
+ USDK\component\common\network\lwip\src\core\snmp
+
+
+ USDK\component\common\network\lwip\src\core\ipv4
+
+
+ USDK\component\common\network\lwip\src\core\ipv4
+
+
+ USDK\component\common\network\lwip\src\core\ipv4
+
+
+ USDK\component\common\network\lwip\src\core\ipv4
+
+
+ USDK\component\common\network\lwip\src\core\ipv4
+
+
+ USDK\component\common\network\lwip\src\core\ipv4
+
+
+ USDK\component\common\network\lwip\src\core\ipv4
+
+
+ USDK\component\common\network\lwip\src\core\ipv4
+
+
+ USDK\component\common\network\lwip\port\realtek\freertos
+
+
+ USDK\component\common\network\lwip\port\realtek\freertos
+
+
+
\ No newline at end of file
diff --git a/RTLGDB/RTLGDB.vcxproj.user b/RTLGDB/RTLGDB.vcxproj.user
new file mode 100644
index 0000000..7987cf1
--- /dev/null
+++ b/RTLGDB/RTLGDB.vcxproj.user
@@ -0,0 +1,12 @@
+п»ї
+
+
+ C:\RTL\6-2017-q2\bin\arm-none-eabi-gdb.exe
+ $(ProjectDir)Debug\obj\Debug.axf
+ OCDDebugger
+ localhost:2331
+
+
+ OCDDebugger
+
+
\ No newline at end of file
diff --git a/RTLGDB/USDK/Makefile b/RTLGDB/USDK/Makefile
new file mode 100644
index 0000000..108d413
--- /dev/null
+++ b/RTLGDB/USDK/Makefile
@@ -0,0 +1,60 @@
+include userset.mk
+
+all: ram_all
+mp: ram_all_mp
+
+.PHONY: ram_all
+ram_all:
+ @$(MAKE) -f $(SDK_PATH)sdkbuild.mk
+ @$(MAKE) -f $(SDK_PATH)flasher.mk genbin1 genbin23
+
+.PHONY: ram_all_mp
+ram_all_mp:
+ @$(MAKE) -f $(SDK_PATH)sdkbuild.mk mp
+ @$(MAKE) -f $(SDK_PATH)flasher.mk mp
+
+.PHONY: clean clean_all
+clean:
+ @$(MAKE) -f $(SDK_PATH)sdkbuild.mk clean
+
+clean_all:
+ @$(MAKE) -f $(SDK_PATH)sdkbuild.mk clean_all
+
+.PHONY: flashburn runram reset test readfullflash flashwebfs flashboot
+flashboot:
+ @$(MAKE) -f $(SDK_PATH)flasher.mk flashboot
+
+flashburn:
+ #JLinkGDB-WrFlash.bat
+ @$(MAKE) -f $(SDK_PATH)flasher.mk flashburn
+
+flash_OTA:
+ @$(MAKE) -f $(SDK_PATH)flasher.mk flash_OTA
+
+webfs:
+ @$(MAKE) -f webfs.mk
+
+flashwebfs:
+ @$(MAKE) -f webfs.mk
+ @$(MAKE) -f $(SDK_PATH)flasher.mk flashwebfs
+ #JLinkGDB-WrWebFs.bat
+
+runram:
+ #JLink-RunRAM.bat
+ @$(MAKE) --f $(SDK_PATH)flasher.mk runram
+
+runsdram:
+ #JLink-RunRAM.bat
+ @$(MAKE) --f $(SDK_PATH)flasher.mk runsdram
+
+ reset:
+ #JLink-Reset.bat
+ @$(MAKE) -f $(SDK_PATH)flasher.mk reset
+
+test:
+ JLink-RTL00ConsoleROM.bat
+ #@make -f flasher.mk test
+
+readfullflash:
+ #JLink-RdFullFlash.bat
+ @$(MAKE) -f $(SDK_PATH)flasher.mk readfullflash
\ No newline at end of file
diff --git a/RTLGDB/USDK/component/common/api/at_cmd/atcmd_cloud.c b/RTLGDB/USDK/component/common/api/at_cmd/atcmd_cloud.c
new file mode 100644
index 0000000..61d6a3b
--- /dev/null
+++ b/RTLGDB/USDK/component/common/api/at_cmd/atcmd_cloud.c
@@ -0,0 +1,175 @@
+#include
+#include "log_service.h"
+#include "cmsis_os.h"
+#include
+
+#if CONFIG_JOYLINK
+#if 1
+void fATCJ(void *arg)
+{
+ extern void joylink_erase(void);
+ printf("\r\n[ATCJ] Erase wifi and joylink info.");
+ if(arg){
+ printf("\r\n[ATCJ]Usage : ATCJ");
+ return;
+ }
+ joylink_erase();
+}
+#else
+void fATCJ(void *arg)
+{
+ extern void cmd_jd_smart(int argc, char **argv);
+ int argc;
+ char *argv[MAX_ARGC] = {0};
+ printf("[ATCJ]:simple config command for jdsmart\n\r");
+ if(!arg){
+ printf("[ATCJ]Usage: ATCJ=simple_config\n\r");
+ return;
+ }
+ argv[0] = "simple_config";
+ if((argc = parse_param(arg, argv)) > 1){
+ cmd_jd_smart(argc, argv);
+ }
+ else
+ printf("[ATCJ]Usage: ATCJ=simple_config\n\r");
+}
+#endif
+#endif
+
+
+#if CONFIG_GAGENT
+void fATCG(void *arg)
+{
+ example_gagent();
+}
+void fATCE(void *arg)
+{//Erase gagent config flash
+ extern int GAgent_DevEraseConfigData();
+ GAgent_DevEraseConfigData();
+}
+#endif
+
+#if CONFIG_QQ_LINK
+void fATCQ(void *arg)
+{
+ int argc;
+ unsigned char *argv[MAX_ARGC] = {0};
+ extern void device_write_sn_license(int argc, unsigned char **argv);
+ extern void device_erase_all(int argc, unsigned char **argv);
+
+ if(!arg)
+ {
+ printf("\r\n[ATCQ] Write sn/license into flash or Erase all info\r\n");
+ printf("\r\n[ATCQ] Usage: ATCQ=erase");
+ printf("\r\n[ATCQ] Usage: ATCQ=sn,xxxxxxxx\r\n ATCQ=licensepart1,xxxxxxxx\r\n ATCQ=licensepart2,xxxxxxxx");
+ return;
+ }
+ argv[0] = "sn&&license&&erase";
+ argc = parse_param(arg, argv);
+ if(argc == 3) // Write sn&&license
+ {
+ device_write_sn_license(argc, argv);
+ }
+ else if(argc == 2) // Erase all info : ATCQ=erase
+ {
+ device_erase_all(argc, argv);
+ }
+ else
+ {
+ printf("\r\n[ATCQ] Usage: ATCQ=erase");
+ printf("\r\n[ATCQ]Usage: ATCQ=sn,xxxxxxxx\r\n ATCQ=licensepart1,xxxxxxxx\r\n ATCQ=licensepart2,xxxxxxxx");
+ }
+}
+#endif
+
+#if CONFIG_AIRKISS_CLOUD
+void fATCW(void *arg)
+{
+ int argc;
+ unsigned char *argv[MAX_ARGC] = {0};
+ extern void airkiss_cloud_write_device_info(int argc, unsigned char **argv);
+ extern void airkiss_cloud_erase_ap_profile(int argc, unsigned char **argv);
+
+ if(!arg) goto USAGE;
+
+ argv[0] = "type/id/licese/erase";
+ argc = parse_param(arg, argv);
+ if(argc == 3) // Write typw/id/license
+ {
+ airkiss_cloud_write_device_info(argc, argv);
+ return;
+ }
+ else if(argc == 2) // Erase wifi profile : ATCW=erase
+ {
+ airkiss_cloud_erase_ap_profile(argc, argv);
+ return;
+ }
+ else
+ goto USAGE;
+
+USAGE:
+ printf("\r\n[ATCW] Write ORDERLY device's type/id/license into flash or Erase wifi profile");
+ printf("\r\n[ATCW] Usage: ATCW=type,xxxxxxxx");
+ printf("\r\n[ATCW] Usage: ATCW=id,xxxxxxxx");
+ printf("\r\n[ATCW] Usage: ATCW=licensepart1,xxxxxxxx\t(80-Byte long)");
+ printf("\r\n[ATCW] Usage: ATCW=licensepart2,xxxxxxxx\t(80-Byte long)");
+ printf("\r\n[ATCW] Usage: ATCW=erase");
+ return;
+}
+#endif
+
+#if CONFIG_ALINK
+extern void example_alink(void);
+extern int alink_erase_wifi_config();
+extern void alink_reset_to_factory(void *arg);
+
+void fATCA(void *arg)
+{
+ example_alink();
+}
+
+void fATCZ(void *arg)
+{
+ //Erase alink config flash
+ alink_erase_wifi_config();
+}
+
+void fATCT(void *arg)
+{
+ alink_reset_to_factory(NULL);
+}
+#endif
+
+void fATCx(void *arg)
+{
+}
+
+log_item_t at_cloud_items[ ] = {
+#if CONFIG_JOYLINK
+ {"ATCJ", fATCJ,},
+#endif
+#if CONFIG_GAGENT
+ {"ATCG", fATCG,},
+ {"ATCE", fATCE,},
+#endif
+#if CONFIG_QQ_LINK
+ {"ATCQ", fATCQ,},
+#endif
+#if CONFIG_AIRKISS_CLOUD
+ {"ATCW", fATCW},
+#endif
+#if CONFIG_ALINK
+ {"ATCA", fATCA,},
+ {"ATCZ", fATCZ,},
+ {"ATCT", fATCT,},
+#endif
+ {"ATC?", fATCx,},
+};
+void at_cloud_init(void)
+{
+ log_service_add_table(at_cloud_items, sizeof(at_cloud_items)/sizeof(at_cloud_items[0]));
+}
+
+#if SUPPORT_LOG_SERVICE
+log_module_init(at_cloud_init);
+#endif
diff --git a/RTLGDB/USDK/component/common/api/at_cmd/atcmd_ethernet.c b/RTLGDB/USDK/component/common/api/at_cmd/atcmd_ethernet.c
new file mode 100644
index 0000000..d43c5fa
--- /dev/null
+++ b/RTLGDB/USDK/component/common/api/at_cmd/atcmd_ethernet.c
@@ -0,0 +1,91 @@
+#include
+#include "log_service.h"
+#include "platform_opts.h"
+#include
+#include "cmsis_os.h"
+#include
+#include
+#include
+
+
+#define _AT_DHCP_ETHERNET_MII_ "ATE0"
+#define _AT_SET_DEFAULT_INTERFACE "ATE1"
+
+#if CONFIG_ETHERNET
+extern int dhcp_ethernet_mii;
+extern int ethernet_if_default;
+extern struct netif xnetif[NET_IF_NUM];
+
+void fATE0(void *arg)
+{
+ int argc;
+ char *argv[MAX_ARGC] = {0};
+ printf("[ATE0]:DHCP configure for ethernet\n\r");
+ if(!arg){
+ printf("[ATE0]Usage to disable DHCP: ATE0=0\n");
+ printf("[ATE0]Usage to enable DHCP: ATE0=1\n");
+ return;
+ }
+ if('0' == *(char *)arg)
+ {
+ dhcp_ethernet_mii = 0;
+ }
+
+ else if('1' == *(char *)arg)
+ {
+ dhcp_ethernet_mii = 1;
+ LwIP_DHCP(NET_IF_NUM - 1, DHCP_START);
+ }
+
+ else
+ {
+ printf("[ATE0]Usage to disable DHCP: ATE0=0\n");
+ printf("[ATE0]Usage to enable DHCP: ATE0=1\n");
+ }
+}
+
+void fATE1(void *arg)
+{
+ int argc;
+ char *argv[MAX_ARGC] = {0};
+ printf("[ATE1]:Set/check the default interface\n\r");
+ if(!arg){
+ if(ethernet_if_default)
+ printf("Ethernet is the default interface\n");
+ else
+ printf("wlan is the default interface\n");
+ return;
+ }
+ if('0' == *(char *)arg)
+ {
+ ethernet_if_default = 0;
+ printf("wlan is set to the default interface\n");
+ }
+
+ else if('1' == *(char *)arg)
+ {
+ ethernet_if_default = 1;
+ printf("ethernet is set to the default interface\n");
+ }
+
+ else
+ {
+ printf("[ATE0]Usage to check the default interface: ATE1\n");
+ printf("[ATE0]Usage to set ethernet as default interface: ATE1=1\n");
+ printf("[ATE0]Usage to set wlan as default interface: ATE1=0\n");
+ }
+}
+
+log_item_t at_ethernet_items[ ] = {
+ {"ATE0", fATE0,},
+ {"ATE1", fATE1,}
+};
+
+void at_ethernet_init(void)
+{
+ log_service_add_table(at_ethernet_items, sizeof(at_ethernet_items)/sizeof(at_ethernet_items[0]));
+}
+
+log_module_init(at_ethernet_init);
+
+#endif
\ No newline at end of file
diff --git a/RTLGDB/USDK/component/common/api/at_cmd/atcmd_lwip.c b/RTLGDB/USDK/component/common/api/at_cmd/atcmd_lwip.c
new file mode 100644
index 0000000..a2b29c8
--- /dev/null
+++ b/RTLGDB/USDK/component/common/api/at_cmd/atcmd_lwip.c
@@ -0,0 +1,2263 @@
+#include
+#include
+
+#ifdef CONFIG_AT_LWIP
+
+#include
+#include "log_service.h"
+#include "atcmd_wifi.h"
+#include "atcmd_lwip.h"
+#include "osdep_service.h"
+#include "osdep_api.h"
+
+#include "tcpip.h"
+#include "lwip/tcp_impl.h"
+
+
+
+#ifndef ATCMD_VER
+#define ATVER_1 1
+#define ATVER_2 2
+#define ATCMD_VER ATVER_2
+#if CONFIG_EXAMPLE_UART_ATCMD
+#define ATCMD_VER ATVER_2
+#else
+#define ATCMD_VER ATVER_1
+#endif
+#endif
+
+//#define MAX_BUFFER 256
+#define MAX_BUFFER (LOG_SERVICE_BUFLEN)
+#define ATCP_STACK_SIZE 512//2048
+
+extern char log_buf[LOG_SERVICE_BUFLEN];
+extern struct netif xnetif[NET_IF_NUM];
+
+static unsigned char tx_buffer[MAX_BUFFER];
+static unsigned char rx_buffer[MAX_BUFFER];
+
+#if ATCMD_VER == ATVER_2
+node node_pool[NUM_NS];
+
+node* mainlist;
+
+static int atcmd_lwip_auto_recv = FALSE;
+volatile int atcmd_lwip_tt_mode = FALSE; //transparent transmission mode
+xTaskHandle atcmd_lwip_tt_task = NULL;
+xSemaphoreHandle atcmd_lwip_tt_sema = NULL;
+volatile int atcmd_lwip_tt_datasize = 0;
+volatile int atcmd_lwip_tt_lasttickcnt = 0;
+
+#ifdef ERRNO
+_WEAK int errno = 0; //LWIP errno
+#endif
+
+static void atcmd_lwip_receive_task(void *param);
+int atcmd_lwip_start_autorecv_task(void);
+int atcmd_lwip_is_autorecv_mode(void);
+void atcmd_lwip_set_autorecv_mode(int enable);
+int atcmd_lwip_start_tt_task(void);
+int atcmd_lwip_is_tt_mode(void);
+void atcmd_lwip_set_tt_mode(int enable);
+int atcmd_lwip_write_info_to_flash(struct atcmd_lwip_conn_info *cur_conn, int enable);
+#else //#if ATCMD_VER == ATVER_2
+
+xTaskHandle server_task = NULL;
+xTaskHandle client_task = NULL;
+
+static int mode = 0;
+static int local_port;
+static int remote_port;
+static char remote_addr[16];
+static int packet_size;
+
+static int sockfd, newsockfd;
+static socklen_t client;
+static struct sockaddr_in serv_addr, cli_addr;
+static int opt = 1;
+
+static int type; //TCP SERVER:1, TCP CLIENT: 2, UDP SERVER:3, UDP CLIENT: 4
+
+static void init_transport_struct(void)
+{
+ mode = 0;
+ local_port = 0;
+ remote_port = 0;
+ sockfd = -1;
+ newsockfd = -1;
+ packet_size = 0;
+ _memset(remote_addr, 0, sizeof(remote_addr));
+ _memset(&client, 0, sizeof(client));
+ _memset(&serv_addr, 0, sizeof(serv_addr));
+
+}
+
+void socket_close(void)
+{
+ close(sockfd);
+ if(server_task != NULL)
+ {
+ vTaskDelete(server_task);
+ server_task = NULL;
+ }
+ if(client_task != NULL)
+ {
+ vTaskDelete(client_task);
+ client_task = NULL;
+ }
+ type = 0;
+ init_transport_struct();
+}
+#endif //#if ATCMD_VER == ATVER_2
+
+static void server_start(void *param)
+{
+ int s_mode;
+ int s_sockfd, s_newsockfd;
+ socklen_t s_client;
+ struct sockaddr_in s_serv_addr, s_cli_addr;
+ int s_local_port;
+ int error_no = 0;
+ int s_opt = 1;
+#if ATCMD_VER == ATVER_2
+ node* ServerNodeUsed = (node*)param;
+ if(ServerNodeUsed){
+ s_mode = ServerNodeUsed->protocol;
+ s_local_port = ServerNodeUsed->port;
+ }
+// else
+//#endif
+#else
+ {
+ s_mode = mode;
+ s_local_port = local_port;
+ s_opt = opt;
+ }
+#endif
+
+ if(s_mode == NODE_MODE_UDP)
+ s_sockfd = socket(AF_INET,SOCK_DGRAM,0);
+ else
+ s_sockfd = socket(AF_INET, SOCK_STREAM, 0);
+
+ if (s_sockfd == INVALID_SOCKET_ID) {
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,"ERROR opening socket");
+ error_no = 5;
+ goto err_exit;
+ }
+
+ if((setsockopt(s_sockfd, SOL_SOCKET, SO_REUSEADDR, (const char *)&s_opt, sizeof(s_opt))) < 0){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,"ERROR on setting socket option");
+ error_no = 6;
+ goto err_exit;
+ }
+
+ memset((char *)&s_serv_addr, 0, sizeof(s_serv_addr));
+ s_serv_addr.sin_family = AF_INET;
+ s_serv_addr.sin_addr.s_addr = INADDR_ANY;
+ s_serv_addr.sin_port = htons(s_local_port);
+
+ if (bind(s_sockfd, (struct sockaddr *)&s_serv_addr,sizeof(s_serv_addr)) < 0) {
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,"ERROR on binding");
+ error_no = 7;
+ goto err_exit;
+ }
+
+#if ATCMD_VER == ATVER_2
+ if(ServerNodeUsed != NULL) {
+ uint8_t *ip = (uint8_t *)LwIP_GetIP(&xnetif[0]);
+ ServerNodeUsed->sockfd = s_sockfd;
+ ServerNodeUsed->addr = ntohl(*((u32_t *)ip));
+ }
+// else
+//#endif
+#else
+ {
+ sockfd = s_sockfd;
+ memcpy(&serv_addr, &s_serv_addr, sizeof(s_serv_addr));
+ }
+#endif
+
+ if (s_mode == NODE_MODE_TCP){//TCP MODE
+ if(listen(s_sockfd , 5) < 0){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,"ERROR on listening");
+ error_no = 8;
+ goto err_exit;
+ }
+#if ATCMD_VER == ATVER_2
+ if(param != NULL) {
+ if(hang_node(ServerNodeUsed) < 0)
+ {
+ error_no = 9;
+ goto err_exit;
+ }else{
+ #if CONFIG_LOG_SERVICE_LOCK
+ log_service_lock();
+ #endif
+ at_printf("\r\n[ATPS] OK"
+ "\r\n[ATPS] con_id=%d",
+ ServerNodeUsed->con_id);
+ at_printf(STR_END_OF_ATCMD_RET);
+ #if CONFIG_LOG_SERVICE_LOCK
+ log_service_unlock();
+ #endif
+ }
+ }
+#endif
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,"The TCP SERVER START OK!");
+ s_client = sizeof(s_cli_addr);
+ while(1){
+ if((s_newsockfd = accept(s_sockfd,(struct sockaddr *) &s_cli_addr,&s_client)) < 0){
+#if ATCMD_VER == ATVER_2
+ if(param != NULL) {
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "[ATPS] ERROR:ERROR on accept");
+ }
+// else
+//#endif
+#else
+ {
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "ERROR on accept");
+ }
+#endif
+ error_no = 10;
+ goto err_exit;
+ }
+ else{
+#if ATCMD_VER == ATVER_2
+ if(param != NULL) {
+ node* seednode = create_node(s_mode, NODE_ROLE_SEED);
+ if(seednode == NULL){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "[ATPS]create node failed!");
+ error_no = 11;
+ goto err_exit;
+ }
+ seednode->sockfd = s_newsockfd;
+ seednode->port = ntohs(s_cli_addr.sin_port);
+ seednode->addr = ntohl(s_cli_addr.sin_addr.s_addr);
+ if(hang_seednode(ServerNodeUsed,seednode) < 0){
+ delete_node(seednode);
+ seednode = NULL;
+ }
+ else{
+ #if CONFIG_LOG_SERVICE_LOCK
+ log_service_lock();
+ #endif
+ at_printf("\r\n[ATPS] A client connected to server[%d]\r\n"
+ "con_id:%d,"
+ "seed,"
+ "tcp,"
+ "address:%s,"
+ "port:%d,"
+ "socket:%d",
+ ServerNodeUsed->con_id,
+ seednode->con_id,
+ inet_ntoa(s_cli_addr.sin_addr.s_addr),
+ ntohs(s_cli_addr.sin_port),
+ seednode->sockfd
+ );
+ at_printf(STR_END_OF_ATCMD_RET);
+ #if CONFIG_LOG_SERVICE_LOCK
+ log_service_unlock();
+ #endif
+ }
+ }
+// else
+//#endif
+#else
+ {
+ newsockfd = s_newsockfd;
+ memcpy(&cli_addr, &s_cli_addr, sizeof(cli_addr));
+ client = s_client;
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,
+ "A client connected to this server :\r\n[PORT]: %d\r\n[IP]:%s",
+ ntohs(cli_addr.sin_port), inet_ntoa(cli_addr.sin_addr.s_addr));
+ }
+#endif
+ }
+ }
+ }
+ else{
+#if ATCMD_VER == ATVER_2
+ if(ServerNodeUsed != NULL) {
+ if(hang_node(ServerNodeUsed) < 0){
+ error_no = 12;
+ goto err_exit;
+ }
+ #if CONFIG_LOG_SERVICE_LOCK
+ log_service_lock();
+ #endif
+ at_printf("\r\n[ATPS] OK"
+ "\r\n[ATPS] con_id=%d",
+ ServerNodeUsed->con_id);
+ at_printf(STR_END_OF_ATCMD_RET);
+ #if CONFIG_LOG_SERVICE_LOCK
+ log_service_unlock();
+ #endif
+ //task will exit itself
+ ServerNodeUsed->handletask = NULL;
+ }
+#endif
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,"The UDP SERVER START OK!");
+ }
+ goto exit;
+err_exit:
+#if ATCMD_VER == ATVER_2
+ if(ServerNodeUsed){
+ //task will exit itself if getting here
+ ServerNodeUsed->handletask = NULL;
+ delete_node(ServerNodeUsed);
+ }
+ //else
+//#endif
+#else
+ {
+ socket_close();
+ }
+#endif
+ #if CONFIG_LOG_SERVICE_LOCK
+ log_service_lock();
+ #endif
+ at_printf("\r\n[ATPS] ERROR:%d", error_no);
+ at_printf(STR_END_OF_ATCMD_RET);
+ #if CONFIG_LOG_SERVICE_LOCK
+ log_service_unlock();
+ #endif
+exit:
+ return;
+}
+
+static void client_start(void *param)
+{
+ int c_mode;
+ int c_remote_port;
+ char c_remote_addr[16];
+ int c_sockfd;
+ struct sockaddr_in c_serv_addr;
+ int error_no = 0;
+#if ATCMD_VER == ATVER_2
+ struct in_addr c_addr;
+ node * ClientNodeUsed = (node *)param;
+ if(ClientNodeUsed){
+ c_mode = ClientNodeUsed->protocol;
+ c_remote_port = ClientNodeUsed->port;
+ c_addr.s_addr = htonl(ClientNodeUsed->addr);
+ if(inet_ntoa_r(c_addr, c_remote_addr, sizeof(c_remote_addr))==NULL){
+ error_no = 6;
+ goto err_exit;
+ }
+ }
+ //else
+//#endif
+#else
+ {
+ c_mode = mode;
+ c_remote_port = remote_port;
+ memcpy(c_remote_addr, remote_addr, 16*sizeof(char));
+ }
+#endif
+ if(c_mode == NODE_MODE_UDP)
+ c_sockfd = socket(AF_INET,SOCK_DGRAM,0);
+ else
+ c_sockfd = socket(AF_INET, SOCK_STREAM, 0);
+
+ if (c_sockfd == INVALID_SOCKET_ID) {
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,"Failed to create sock_fd!");
+ error_no = 7;
+ goto err_exit;
+ }
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,"OK to create sock_fd!");
+ memset(&c_serv_addr, 0, sizeof(c_serv_addr));
+ c_serv_addr.sin_family = AF_INET;
+ c_serv_addr.sin_addr.s_addr = inet_addr(c_remote_addr);
+ c_serv_addr.sin_port = htons(c_remote_port);
+
+#if ATCMD_VER == ATVER_2
+ if(ClientNodeUsed){
+ ClientNodeUsed->sockfd = c_sockfd;
+ }
+ //else
+//#endif
+#else
+ {
+ sockfd = c_sockfd;
+ memcpy(&serv_addr, &c_serv_addr, sizeof(c_serv_addr));
+ }
+#endif
+ if (c_mode == NODE_MODE_TCP){//TCP MODE
+ if(connect(c_sockfd, (struct sockaddr *)&c_serv_addr, sizeof(c_serv_addr)) == 0){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,"Connect to Server successful!");
+#if ATCMD_VER == ATVER_2
+ if(ClientNodeUsed != NULL) {
+ if(hang_node(ClientNodeUsed) < 0){
+ error_no = 8;
+ goto err_exit;
+ }
+ #if CONFIG_LOG_SERVICE_LOCK
+ log_service_lock();
+ #endif
+ at_printf("\r\n[ATPC] OK\r\n[ATPC] con_id=%d",ClientNodeUsed->con_id);
+ at_printf(STR_END_OF_ATCMD_RET);
+ #if CONFIG_LOG_SERVICE_LOCK
+ log_service_unlock();
+ #endif
+ }
+#endif
+ }else{
+#if ATCMD_VER == ATVER_2
+ if(ClientNodeUsed != NULL) {
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,"[ATPC] ERROR:Connect to Server failed!");
+ }
+ //else
+//#endif
+#else
+ {
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,"Connect to Server failed!");
+ }
+#endif
+ error_no = 9;
+ goto err_exit;
+ }
+ }
+ else{
+#if ATCMD_VER == ATVER_2
+ if(ClientNodeUsed != NULL) {
+ if(ClientNodeUsed->local_port){
+ struct sockaddr_in addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family=AF_INET;
+ addr.sin_port=htons(ClientNodeUsed->local_port);
+ addr.sin_addr.s_addr=htonl(INADDR_ANY) ;
+ if (bind(ClientNodeUsed->sockfd, (struct sockaddr *)&addr, sizeof(addr))<0) {
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,"bind sock error!");
+ error_no = 12;
+ goto err_exit;
+ }
+ }
+ if(hang_node(ClientNodeUsed) < 0){
+ error_no = 10;
+ goto err_exit;
+ }
+ #if CONFIG_LOG_SERVICE_LOCK
+ log_service_lock();
+ #endif
+ at_printf("\r\n[ATPC] OK\r\n[ATPC] con_id=%d",ClientNodeUsed->con_id);
+ at_printf(STR_END_OF_ATCMD_RET);
+ #if CONFIG_LOG_SERVICE_LOCK
+ log_service_unlock();
+ #endif
+ }
+#endif
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,"UDP client starts successful!");
+ }
+ goto exit;
+err_exit:
+#if ATCMD_VER == ATVER_2
+ if(ClientNodeUsed)
+ {
+ delete_node(ClientNodeUsed);
+ }
+ //else
+//#endif
+#else
+ {
+ socket_close();
+ }
+#endif
+ #if CONFIG_LOG_SERVICE_LOCK
+ log_service_lock();
+ #endif
+ at_printf("\r\n[ATPC] ERROR:%d", error_no);
+ at_printf(STR_END_OF_ATCMD_RET);
+ #if CONFIG_LOG_SERVICE_LOCK
+ log_service_unlock();
+ #endif
+exit:
+ return;
+}
+
+static void client_start_task(void *param)
+{
+ vTaskDelay(1000);
+#if ATCMD_VER == ATVER_2
+ if(param){
+ client_start(param);
+ vTaskDelete(NULL);
+ return;
+ }
+//#endif
+#else
+ if(remote_addr == NULL){
+ printf("[ERROR] Please using ATP3 to input an valid remote IP address!\n");
+ vTaskDelete(client_task);
+ client_task = NULL;
+ }
+ else if(remote_port == 0){
+ printf("[ERROR] Please using ATP4 to input an valid remote PORT!\n");
+ vTaskDelete(client_task);
+ client_task = NULL;
+ }
+ else{
+ printf("\tStart Client\n\t[IP]: %s\n\t[PORT]:%d\n", remote_addr, remote_port);
+ client_start(param);
+ }
+#endif
+ vTaskDelete(NULL);
+}
+
+static void server_start_task(void *param)
+{
+ vTaskDelay(1000);
+#if ATCMD_VER == ATVER_2
+ if(param != NULL){
+ server_start(param);
+ vTaskDelete(NULL);
+ return;
+ }
+//#endif
+#else
+ if(local_port == 0){
+ printf("[ERROR] Please using ATP2 to input an valid local PORT!\n");
+ vTaskDelete(server_task);
+ server_task = NULL;
+ }
+ else{
+ uint8_t *ip = (uint8_t *)LwIP_GetIP(&xnetif[0]);
+ printf("Start Server\n\t[IP]: %d.%d.%d.%d\n\t[PORT]:%d\n", ip[0], ip[1], ip[2], ip[3], local_port);
+ server_start(param);
+ }
+#endif
+ vTaskDelete(NULL);
+}
+
+//AT Command function
+#if ATCMD_VER == ATVER_1
+void fATP1(void *arg){
+ if(!arg){
+ printf("[ATP1]Usage: ATP1=MODE\n\r");
+ goto exit;
+ }
+ mode = atoi((char*)arg);
+ printf("[ATP1]: _AT_TRANSPORT_MODE_ [%d]\n\r", mode);
+exit:
+ return;
+}
+
+void fATP2(void *arg){
+ if(!arg){
+ printf("[ATP2]Usage: ATP2=LOCAL_PORT\n\r");
+ goto exit;
+ }
+ local_port = atoi((char*)arg);
+ printf("[ATP2]: _AT_TRANSPORT_LOCAL_PORT_ [%d]\n\r", local_port);
+
+exit:
+ return;
+}
+
+void fATP3(void *arg){
+ if(!arg){
+ printf("[ATP3]Usage: ATP3=REMOTE_IP\n\r");
+ goto exit;
+ }
+ strcpy((char*)remote_addr, (char*)arg);
+ printf("[ATP3]: _AT_TRANSPORT_REMOTE_IP_ [%s]\n\r", remote_addr);
+
+exit:
+ return;
+}
+
+void fATP4(void *arg){
+ if(!arg){
+ printf("[ATP4]Usage: ATP4=REMOTE_PORT\n\r");
+ goto exit;
+ }
+ remote_port = atoi((char*)arg);
+ printf("[ATP4]: _AT_TRANSPORT_REMOTE_PORT_ [%d]\n\r", remote_port);
+
+exit:
+ return;
+}
+
+void fATP5(void *arg){
+ int server_status = 0;
+ if(!arg){
+ printf("[ATP5]Usage: ATP5=0/1(0:server disable; 1: server enable)\n\r");
+ goto exit;
+ }
+ server_status = atoi((char*)arg);
+ printf("[ATP5]: _AT_TRANSPORT_START_SERVER_ [%d]\n\r", server_status);
+ if(mode == 0){
+ if(server_status == 0){
+ socket_close();
+ type = 0;
+ }
+ else if(server_status == 1){
+ if(server_task == NULL)
+ {
+ if(xTaskCreate(server_start_task, ((const char*)"server_start_task"), ATCP_STACK_SIZE, NULL, ATCMD_LWIP_TASK_PRIORITY, &server_task) != pdPASS)
+ printf("[ATP5]ERROR: Create tcp server task failed.\r\n");
+ }
+ type = 1;
+ }
+ else
+ printf("[ATP5]ERROR: Just support two mode : 0 or 1\n\r");
+ }
+ else if(mode == 1){
+ if(server_status == 0){
+ socket_close();
+ type = 0;
+ }
+ else if(server_status == 1){
+ if(server_task == NULL)
+ {
+ if(xTaskCreate(server_start_task, ((const char*)"server_start_task"), ATCP_STACK_SIZE, NULL, ATCMD_LWIP_TASK_PRIORITY, &server_task) != pdPASS)
+ printf("[ATP5]ERROR: Create udp server task failed.\n");
+ }
+ type = 3;
+ }
+ else
+ printf("[ATP5]ERROR: Just support two mode : 0 or 1\n\r");
+ }
+ else
+ printf("[ATP5]Error: mode(TCP/UDP) can't be empty\n\r");
+
+exit:
+ return;
+}
+
+void fATP6(void *arg){
+ int client_status = 0;
+ if(!arg){
+ printf("[ATP6]Usage: ATP6=0/1(0:Client disable; 1: Client enable)\n\r");
+ goto exit;
+ }
+ client_status = atoi((char*)arg);
+ printf("[ATP6]: _AT_TRANSPORT_START_CLIENT_ [%d]\n\r", client_status);
+ if(mode == 0){
+ if(client_status == 0){
+ socket_close();
+ type = 0;
+ }
+ else if(client_status == 1){
+ printf("[ATP6]TCP Client mode will start\n");
+ if(client_task == NULL)
+ {
+ if(xTaskCreate(client_start_task, ((const char*)"client_start_task"), ATCP_STACK_SIZE, NULL, ATCMD_LWIP_TASK_PRIORITY, &client_task) != pdPASS)
+ printf("[ATP6]ERROR: Create tcp client task failed.\n");
+ }
+ type = 2;
+ }
+ else
+ printf("[ATP6]ERROR: Just support two mode : 0 or 1\n\r");
+ }
+ else if(mode == 1){
+ if(client_status == 0){
+ socket_close();
+ type = 0;
+ }
+ else if(client_status == 1){
+ if(client_task == NULL)
+ {
+ if(xTaskCreate(client_start_task, ((const char*)"client_start_task"), ATCP_STACK_SIZE, NULL, ATCMD_LWIP_TASK_PRIORITY, &client_task) != pdPASS)
+ printf("[ATP6]ERROR: Create udp client task failed.\n");
+ }
+ type = 4;
+ }
+ else
+ printf("[ATP6]ERROR: Just support two mode : 0 or 1\n\r");
+ }
+ else
+ printf("[ATP6]Error: mode(TCP/UDP) can't be empty\n\r");
+
+exit:
+ return;
+}
+
+void fATPZ(void *arg){
+ uint8_t *ip;
+ printf("\nThe current Transport settings:\n");
+ printf("==============================\n");
+ if(mode == 0)
+ printf(" Protocol: TCP\n");
+ else if(mode == 1)
+ printf(" Protocol: UDP\n");
+
+ ip = (uint8_t *)LwIP_GetIP(&xnetif[0]);
+ printf(" LOCAL_IP => %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
+ printf(" LOCAL_PORT => %d\n", local_port);
+ printf(" REMOTE_IP => %s\n", remote_addr);
+ printf(" REMOTE_PORT => %d\n", remote_port);
+
+// printf("\n\r");
+}
+
+void fATR0(void *arg){
+ if(packet_size <= 0){
+ packet_size = MAX_BUFFER;
+ printf("[ATR0]Notice: Didn't set the value of packet_size, will using the MAX_BUFFER: %d\n", MAX_BUFFER);
+ }
+ memset(rx_buffer, 0, MAX_BUFFER);
+ if(type == 1){//tcp server
+ if((read(newsockfd,rx_buffer,MAX_BUFFER)) > 0)
+ printf("[ATR0]Receive the data:%s\n with packet_size: %d\n", rx_buffer, packet_size);
+ else
+ printf("[ATR0]ERROR: Failed to receive data!\n");
+ close(newsockfd);
+ newsockfd = -1;
+ }
+ else{
+ if((read(sockfd,rx_buffer,MAX_BUFFER)) > 0)
+ printf("[ATR0]Receive the data:%s\n with packet_size: %d\n", rx_buffer, packet_size);
+ else
+ printf("[ATR0]ERROR: Failed to receive data!\n");
+ }
+}
+
+void fATR1(void *arg){
+ int size;
+ if(!arg){
+ printf("[ATR1]Usage: ATR1=packet_size(cannot exceed %d)\n\r", MAX_BUFFER);
+ goto exit;
+ }
+ size = atoi((char*)arg);
+ printf("[ATR1]: _AT_TRANSPORT_RECEIVE_PACKET_SIZE_ [%d]\n\r", size);
+ if(size < 1)
+ printf("[ATR1]Error: packet size need be larger than 0!\n\r");
+ else if(size > MAX_BUFFER)
+ printf("[ATR1]Error: packet size exceeds the MAX_BUFFER value: %d!\n\r", MAX_BUFFER);
+ else
+ packet_size = size;
+exit:
+ return;
+}
+
+
+void fATRA(void *arg){
+ if(!arg){
+ printf("[ATRA]Usage: ATRA=[data](Data size cannot exceed the MAX_BUFFER SIZE: %d)\n\r", MAX_BUFFER);
+ return;
+ }
+
+ if(packet_size <= 0){
+ packet_size = MAX_BUFFER;
+ printf("[ATRA]Notice: Didn't set the value of packet_size, will using the MAX_BUFFER SIZE: %d\n", MAX_BUFFER);
+ }
+
+
+ int argc;
+ char *argv[MAX_ARGC] = {0};
+
+ if((argc = parse_param(arg, argv)) != 2){
+ printf("[ATRA]Usage: ATRA=[data](Data size cannot exceed the MAX_BUFFER SIZE: %d)\n\r", MAX_BUFFER);
+ goto exit;
+ }
+ else
+ printf("[ATRA]: _AT_TRANSPORT_WRITE_DATA_ [%s]\n\r", argv[1]);
+ memset(tx_buffer, 0, MAX_BUFFER);
+ memcpy(tx_buffer, argv[1], strlen(argv[1]));
+
+ if(type == 1){//tcp server
+ if((write(newsockfd,tx_buffer,strlen(tx_buffer))) > 0)
+ printf("[ATRA] Sending data:%s\n with packet_size:%d\n", tx_buffer, packet_size);
+ else
+ printf("[ATRA]ERROR: Failed to send data\n");
+ close(newsockfd);
+ newsockfd = -1;
+ }
+ else if(type == 4){//udp client
+ int ret = 0;
+ ret = sendto(sockfd, tx_buffer, strlen(tx_buffer), 0, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
+
+ printf("The value of ret is %d\n", ret);
+ }
+ else if(type == 3)
+ printf("The UDP Server mode not support Sending data service!\n");
+ else{
+ if((write(sockfd,tx_buffer, strlen(tx_buffer))) > 0)
+ printf("[ATRA] Sending data:%s\n with packet_size:%d\n", tx_buffer, packet_size);
+ else
+ printf("[ATRA]ERROR: Failed to send data\n");
+ }
+exit:
+ return;
+}
+
+void fATRB(void *arg){
+ int size;
+ if(!arg){
+ printf("[ATRB]Usage: ATRB=packet_size(cannot exceed %d)\n\r", MAX_BUFFER);
+ goto exit;
+ }
+ size = atoi((char*)arg);
+ printf("[ATRB]: _AT_TRANSPORT_WRITE_PACKET_SIZE_ [%d]\n\r", size);
+ if(size < 1)
+ printf("[ATRB]Error: packet size need be larger than 0!\n\r");
+ else if(size > MAX_BUFFER)
+ printf("[ATRB]Error: packet size exceeds the MAX_BUFFER value: %d!\n\r", MAX_BUFFER);
+ else
+ packet_size = size;
+exit:
+ return;
+}
+#endif
+#if ATCMD_VER == ATVER_2
+void fATP0(void *arg){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,
+ "[ATP0]: _AT_TRANSPORT_ERRNO");
+#ifdef ERRNO
+ at_printf("\r\n[ATP0] OK:%d", errno);
+#else
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,"errno isn't enabled");
+ at_printf("\r\n[ATP0] ERROR");
+#endif
+}
+
+void fATPC(void *arg){
+
+ int argc;
+ char* argv[MAX_ARGC] = {0};
+ node* clientnode = NULL;
+ int mode = 0;
+ int remote_port;
+ int local_port = 0;
+ //char remote_addr[DNS_MAX_NAME_LENGTH];
+ struct in_addr addr;
+ int error_no = 0;
+#if LWIP_DNS
+ struct hostent *server_host;
+#endif
+
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,
+ "[ATPC]: _AT_TRANSPORT_START_CLIENT");
+
+ if(atcmd_lwip_is_tt_mode() && mainlist->next){
+ error_no = 13;
+ goto err_exit;
+ }
+
+ argc = parse_param(arg, argv);
+ if(argc < 4){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "[ATPC] Usage: ATPC=,,,[]");
+ error_no = 1;
+ goto err_exit;
+ }
+
+ mode = atoi((char*)argv[1]);//tcp or udp
+ //strcpy((char*)remote_addr, (char*)argv[2]);
+
+ remote_port = atoi((char*)argv[3]);
+ if (inet_aton(argv[2], &addr) == 0)
+ {
+#if LWIP_DNS
+ server_host = gethostbyname(argv[2]);
+ if (server_host){
+ memcpy(&addr, server_host->h_addr, 4);
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,
+ "[ATPC] Found name '%s' = %s",
+ argv[2],
+ inet_ntoa(addr)
+ );
+ }
+ else
+#endif
+ {
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "[ATPC] ERROR: Host '%s' not found.", argv[2]);
+ error_no = 2;
+ goto err_exit;
+ }
+ }
+
+ if(remote_port < 0 || remote_port > 65535) {
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "[ATPC] ERROR: remote port invalid");
+ error_no = 3;
+ goto err_exit;
+ }
+
+ if(argv[4]){
+ local_port = atoi((char*)argv[4]);
+ if(local_port < 0 || local_port > 65535) {
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "[ATPC] ERROR: local port invalid");
+ error_no = 11;
+ goto err_exit;
+ }
+ }
+
+ clientnode = create_node(mode, NODE_ROLE_CLIENT);
+ if(clientnode == NULL){
+ error_no = 4;
+ goto err_exit;
+ }
+ clientnode->port = remote_port;
+ clientnode->addr = ntohl(addr.s_addr);
+ clientnode->local_port = local_port;
+
+ if(xTaskCreate(client_start_task, ((const char*)"client_start_task"), ATCP_STACK_SIZE, clientnode, ATCMD_LWIP_TASK_PRIORITY, NULL) != pdPASS)
+ {
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "[ATPC] ERROR: Create tcp/udp client task failed.");
+ error_no = 5;
+ goto err_exit;
+ }
+
+ goto exit;
+err_exit:
+ if(clientnode)
+ delete_node(clientnode);
+ at_printf("\r\n[ATPC] ERROR:%d", error_no);
+exit:
+ return;
+}
+
+
+void fATPS(void *arg){
+ int argc;
+ char *argv[MAX_ARGC] = {0};
+ node* servernode = NULL;
+ int mode;
+ int local_port;
+ int error_no = 0;
+
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,
+ "[ATPS]: _AT_TRANSPORT_START_SERVER");
+
+ if(atcmd_lwip_is_tt_mode()){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "[ATPS] ERROR: Server can only start when TT is disabled");
+ error_no = 13;
+ goto err_exit;
+ }
+
+ argc = parse_param(arg, argv);
+ if(argc != 3){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "[ATPS] Usage: ATPS=[TCP:0/UDP:1],[Local port(1~65535)]");
+ error_no = 1;
+ goto err_exit;
+ }
+
+ mode = atoi((char*)argv[1]);
+ local_port = atoi((char*)argv[2]);
+
+ if(local_port < 0 || local_port > 65535){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "[ATPS] Usage: ATPS=[TCP:0/UDP:1],[Local port]");
+ error_no = 2;
+ goto err_exit;
+ }
+
+ servernode = create_node(mode, NODE_ROLE_SERVER);
+ if(servernode == NULL){
+ error_no = 3;
+ goto err_exit;
+ }
+ servernode->port = local_port;
+
+ if(xTaskCreate(server_start_task, ((const char*)"server_start_task"), ATCP_STACK_SIZE, servernode, ATCMD_LWIP_TASK_PRIORITY, &servernode->handletask) != pdPASS)
+ {
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "[ATPS] ERROR: Create tcp/udp server task failed.");
+ error_no = 4;
+ goto err_exit;
+ }
+
+ goto exit;
+err_exit:
+ if(servernode)
+ delete_node(servernode);
+ at_printf("\r\n[ATPS] ERROR:%d", error_no);
+exit:
+ return;
+}
+
+void socket_close_all(void)
+{
+ node *currNode = mainlist->next;
+
+ while(currNode)
+ {
+ delete_node(currNode);
+ currNode = mainlist->next;
+ }
+ currNode = NULL;
+}
+
+void fATPD(void *arg){
+ int con_id = INVALID_CON_ID;
+ int error_no = 0;
+ node *s_node;
+
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,
+ "[ATPD]: _AT_TRANSPORT_CLOSE_CONNECTION");
+
+ if(!arg){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "[ATPD] Usage: ATPD=con_id or 0 (close all)");
+ error_no = 1;
+ goto exit;
+ }
+ con_id = atoi((char*)arg);
+
+ if(con_id == 0){
+ if(atcmd_lwip_is_autorecv_mode()){
+ atcmd_lwip_set_autorecv_mode(FALSE);
+ }
+ socket_close_all();
+ goto exit;
+ }
+
+ s_node = seek_node(con_id);
+ if(s_node == NULL){
+ error_no = 3;
+ goto exit;
+ }
+ delete_node(s_node);
+
+exit:
+ s_node = NULL;
+ if(error_no)
+ at_printf("\r\n[ATPD] ERROR:%d", error_no);
+ else
+ at_printf("\r\n[ATPD] OK");
+ return;
+}
+
+int atcmd_lwip_send_data(node *curnode, u8 *data, u16 data_sz, struct sockaddr_in cli_addr){
+ int error_no = 0;
+
+ if((curnode->protocol == NODE_MODE_UDP) && (curnode->role == NODE_ROLE_SERVER))
+ {
+ if (sendto(curnode->sockfd, data, data_sz, 0, (struct sockaddr *)&cli_addr, sizeof(cli_addr)) <= 0 ){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "[ATPT] ERROR:Failed to send data");
+ error_no = 5;
+ }
+ }else{
+ if(curnode->protocol == NODE_MODE_UDP) //UDP server
+ {
+ struct sockaddr_in serv_addr;
+ memset(&serv_addr, 0, sizeof(serv_addr));
+ serv_addr.sin_family = AF_INET;
+ serv_addr.sin_port = htons(curnode->port);
+ serv_addr.sin_addr.s_addr = htonl(curnode->addr);
+ if(sendto( curnode->sockfd, data, data_sz, 0, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) <= 0){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "[ATPT] ERROR:Failed to send data\n");
+ error_no = 6;
+ }
+ }else if(curnode->protocol == NODE_MODE_TCP)//TCP server
+ {
+ if(curnode->role == NODE_ROLE_SERVER){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "[ATPT] ERROR: TCP Server must send data to the seed");
+ error_no = 7;
+ goto exit;
+ }
+
+ if((write(curnode->sockfd, data, data_sz)) <= 0){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "[ATPT] ERROR:Failed to send data\n");
+ error_no = 8;
+ }
+ }
+ }
+
+exit:
+ return error_no;
+}
+
+void fATPT(void *arg){
+
+ int argc;
+ char *argv[MAX_ARGC] = {0};
+ int con_id = INVALID_CON_ID;
+ int error_no = 0;
+ node* curnode = NULL;
+ struct sockaddr_in cli_addr;
+ int data_sz;
+ int data_pos = C_NUM_AT_CMD + C_NUM_AT_CMD_DLT+ strlen(arg) + 1;
+ u8 *data = (u8 *)log_buf + data_pos;
+
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,
+ "[ATPT]: _AT_TRANSPORT_SEND_DATA");
+
+ argc = parse_param(arg, argv);
+
+ if(argc != 3 && argc != 5) {
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "[ATPT] Usage: ATPT=,"
+ "[,,]"
+ ":(MAX %d)",
+ MAX_BUFFER);
+ error_no = 1;
+ goto exit;
+ }
+
+ data_sz = atoi((char*)argv[1]);
+ if(data_sz > MAX_BUFFER){
+ error_no = 2;
+ goto exit;
+ }
+
+ con_id = atoi((char*)argv[2]);
+ curnode = seek_node(con_id);
+ if(curnode == NULL){
+ error_no = 3;
+ goto exit;
+ }
+
+ if((curnode->protocol == NODE_MODE_UDP)
+ &&(curnode->role == NODE_ROLE_SERVER))
+ {
+ char udp_clientaddr[16]={0};
+ strcpy((char*)udp_clientaddr, (char*)argv[3]);
+ cli_addr.sin_family = AF_INET;
+ cli_addr.sin_port = htons(atoi((char*)argv[4]));
+ if (inet_aton(udp_clientaddr , &cli_addr.sin_addr) == 0)
+ {
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "[ATPT]ERROR:inet_aton() failed");
+ error_no = 4;
+ goto exit;
+ }
+ }
+ error_no = atcmd_lwip_send_data(curnode, data, data_sz, cli_addr);
+exit:
+ if(error_no)
+ at_printf("\r\n[ATPT] ERROR:%d,%d", error_no, con_id);
+ else
+ at_printf("\r\n[ATPT] OK,%d", con_id);
+ return;
+}
+
+void fATPR(void *arg){
+
+ int argc,con_id = INVALID_CON_ID;
+ char *argv[MAX_ARGC] = {0};
+ int error_no = 0;
+ int recv_size = 0;
+ int packet_size = 0;
+ node* curnode = NULL;
+ u8_t udp_clientaddr[16] = {0};
+ u16_t udp_clientport = 0;
+
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,
+ "[ATPR]: _AT_TRANSPORT_RECEIVE_DATA");
+
+ if(atcmd_lwip_is_autorecv_mode()){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "[ATPR] ERROR: Receive changed to auto mode.");
+ error_no = 10;
+ goto exit;
+ }
+
+ argc = parse_param(arg, argv);
+ if( argc != 3){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "[ATPR] Usage: ATPR =,\n\r");
+ error_no = 1;
+ goto exit;
+ }
+
+ con_id = atoi((char*)argv[1]);
+ if(con_id <= 0 || con_id > NUM_NS){
+ error_no = 9;
+ goto exit;
+ }
+
+ packet_size = atoi((char*)argv[2]);
+
+ if(packet_size <= 0 || packet_size > MAX_BUFFER){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "[ATPR] Recv Size(%d) exceeds MAX_BUFFER(%d)", packet_size,
+ MAX_BUFFER);
+ error_no = 2;
+ goto exit;
+ }
+
+ curnode = seek_node(con_id);
+ if(curnode == NULL){
+ error_no = 3;
+ goto exit;
+ }
+
+ if(curnode->protocol == NODE_MODE_TCP && curnode->role == NODE_ROLE_SERVER){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "[ATPR] ERROR: TCP Server must receive data from the seed");
+ error_no = 6;
+ goto exit;
+ }
+
+ memset(rx_buffer, 0, MAX_BUFFER);
+ error_no = atcmd_lwip_receive_data(curnode, rx_buffer, ETH_MAX_MTU, &recv_size, udp_clientaddr, &udp_clientport);
+exit:
+ if(error_no == 0){
+ if(curnode->protocol == NODE_MODE_UDP && curnode->role == NODE_ROLE_SERVER){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,
+ "\r\n[ATPR] OK,%d,%d,%s,%d:", recv_size, con_id, udp_clientaddr, udp_clientport);
+ at_printf("\r\n[ATPR] OK,%d,%d,%s,%d:", recv_size, con_id, udp_clientaddr, udp_clientport);
+ }
+ else{
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,
+ "\r\n[ATPR] OK,%d,%d:", recv_size, con_id);
+ at_printf("\r\n[ATPR] OK,%d,%d:", recv_size, con_id);
+ }
+ if(recv_size)
+ at_print_data(rx_buffer, recv_size);
+ }
+ else
+ at_printf("\r\n[ATPR] ERROR:%d,%d", error_no, con_id);
+ return;
+}
+
+void fATPK(void *arg){
+
+ int argc;
+ int error_no = 0;
+ int enable = 0;
+ char *argv[MAX_ARGC] = {0};
+
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,
+ "[ATPK]: _AT_TRANSPORT_AUTO_RECV");
+
+ argc = parse_param(arg, argv);
+ if( argc < 2){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "[ATPK] Usage: ATPK=<0/1>\n\r");
+ error_no = 1;
+ goto exit;
+ }
+
+ enable = atoi((char*)argv[1]);
+
+ if(enable){
+ if(atcmd_lwip_is_autorecv_mode()){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS, "[ATPK] already enter auto receive mode");
+ }
+ else{
+ if(atcmd_lwip_start_autorecv_task())
+ error_no = 2;
+ }
+ }else{
+ if(atcmd_lwip_is_autorecv_mode())
+ atcmd_lwip_set_autorecv_mode(FALSE);
+ else{
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,"[ATPK] already leave auto receive mode");
+ }
+ }
+
+exit:
+ if(error_no)
+ at_printf("\r\n[ATPK] ERROR:%d", error_no);
+ else
+ at_printf("\r\n[ATPK] OK");
+ return;
+}
+
+void fATPU(void *arg){
+
+ int argc;
+ int error_no = 0;
+ int enable = 0;
+ char *argv[MAX_ARGC] = {0};
+
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,
+ "[ATPU]: _AT_TRANSPORT_TT_MODE");
+
+ argc = parse_param(arg, argv);
+ if( argc < 2){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "[ATPU] Usage: ATPU=<1>\n\r");
+ error_no = 1;
+ goto exit;
+ }
+
+ enable = atoi((char*)argv[1]);
+
+ if(enable){
+ if(!mainlist->next){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR, "[ATPU] No conn found");
+ error_no = 2;
+ }else if(mainlist->next->role == NODE_ROLE_SERVER){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR, "[ATPU] No TT mode for server");
+ error_no = 3;
+ }
+ else if(mainlist->next->next || mainlist->next->nextseed){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR, "[ATPU] More than one conn found");
+ error_no = 4;
+ }
+ else{
+ if(atcmd_lwip_start_tt_task()){
+ error_no = 5;
+ }
+ }
+ }
+
+exit:
+ if(error_no)
+ at_printf("\r\n[ATPU] ERROR:%d", error_no);
+ else
+ at_printf("\r\n[ATPU] OK");
+ return;
+}
+
+//ATPL=
+void fATPL(void *arg)
+{
+ int argc, error_no = 0;
+ char *argv[MAX_ARGC] = {0};
+
+ if(!arg){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "\r\n[ATPL] Usage : ATPL=");
+ error_no = 1;
+ goto exit;
+ }
+ argc = parse_param(arg, argv);
+ if(argc != 2){
+ error_no = 2;
+ goto exit;
+ }
+
+ //ENABLE LWIP FAST CONNECT
+ if(argv[1] != NULL){
+ int enable = atoi(argv[1]);
+ struct atcmd_lwip_conn_info cur_conn = {0};
+ node *cur_node = mainlist->next;
+ if(enable && cur_node == NULL){
+ error_no = 3;
+ goto exit;
+ }
+ cur_conn.role = cur_node->role;
+ cur_conn.protocol = cur_node->protocol;
+ cur_conn.remote_addr = cur_node->addr;
+ cur_conn.remote_port = cur_node->port;
+ cur_conn.local_addr = cur_node->local_addr;
+ cur_conn.local_port = cur_node->local_port;
+ atcmd_lwip_write_info_to_flash(&cur_conn, enable);
+ }
+
+exit:
+ if(error_no == 0)
+ at_printf("\r\n[ATPL] OK");
+ else
+ at_printf("\r\n[ATPL] ERROR:%d",error_no);
+
+ return;
+}
+
+extern void do_ping_call(char *ip, int loop, int count);
+void fATPP(void *arg){
+ int count, argc = 0;
+ char buf[32] = {0};
+ char *argv[MAX_ARGC] = {0};
+ int con_id=INVALID_CON_ID;
+ int error_no = 0;
+
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,
+ "[ATPP]: _AT_TRANSPORT_PING");
+
+ if(!arg){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,"[ATPP] Usage: ATPP=xxxx.xxxx.xxxx.xxxx[y/loop] or ATPP=[con_id],[y/loop]\n\r");
+ error_no = 1;
+ goto exit;
+ }
+
+ argc = parse_param(arg, argv);
+
+ if( strlen(argv[1]) < 3 )
+ {
+ node* curnode;
+ struct in_addr addr;
+ con_id = atoi( (char*)argv[1] );
+ curnode = seek_node(con_id);
+ if(curnode == NULL){
+ error_no = 2;
+ goto exit;
+ }
+ if( curnode->role == 1){ //ping remote server
+ addr.s_addr = htonl(curnode->addr);
+ inet_ntoa_r(addr, buf, sizeof(buf));
+ }else if( curnode->role == 0){//ping local server
+ strcpy(buf,SERVER);
+ }else if( curnode->role == 2){ //ping seed
+ strcpy(buf,(char*) curnode->addr);
+ }
+ }else
+ strcpy(buf, argv[1]);
+
+ if(argc == 2){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,"[ATPP]Repeat Count: 5");
+ do_ping_call(buf, 0, 5); //Not loop, count=5
+ }else{
+ if(strcmp(argv[2], "loop") == 0){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,"[ATPP]Repeat Count: %s", "loop");
+ do_ping_call(buf, 1, 0); //loop, no count
+ }else{
+ count = atoi(argv[2]);
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,"[ATPP]Repeat Count: %d", count);
+ do_ping_call(buf, 0, count); //Not loop, with count
+ }
+ }
+
+exit:
+ if(error_no)
+ at_printf("\r\n[ATPP] ERROR:%d", error_no);
+ else
+ at_printf("\r\n[ATPP] OK");
+ return;
+}
+
+void fATPI(void *arg){
+ node* n = mainlist->next;
+ struct in_addr addr;
+
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,
+ "[ATPI]: _AT_TRANSPORT_CONNECTION_INFO");
+
+ while (n != NULL)
+ {
+ if(n->con_id == 0)
+ continue;
+
+ at_printf("\r\ncon_id:%d,", n->con_id);
+
+ if(n->role == 0)
+ at_printf("server,");
+ else
+ at_printf("client,");
+ if(n->protocol == 0)
+ at_printf("tcp,");
+ else
+ at_printf("udp,");
+
+ addr.s_addr = htonl(n->addr);
+ at_printf("address:%s,port:%d,socket:%d", inet_ntoa(addr) ,n->port, n->sockfd);
+ if(n->nextseed != NULL)
+ {
+ node* seed = n;
+ do{
+ seed = seed->nextseed;
+ at_printf("\r\ncon_id:%d,seed,", seed->con_id);
+ if(seed->protocol == 0)
+ at_printf("tcp,");
+ else
+ at_printf("udp,");
+ addr.s_addr = htonl(seed->addr);
+ at_printf("address:%s,port:%d,socket:%d", inet_ntoa(addr), seed->port, seed->sockfd);
+ }while (seed->nextseed != NULL);
+ }
+ n = n->next;
+ }
+
+ at_printf("\r\n[ATPI] OK");
+
+ return;
+}
+
+void init_node_pool(void){
+ int i;
+ memset(node_pool, 0, sizeof(node_pool));
+ for(i=0;inext )
+ {
+ if(currNode == n){
+ prevNode->next = currNode->next;
+ }
+
+ if(currNode->role != NODE_ROLE_SERVER)
+ continue;
+
+ precvSeed = currNode;
+ currSeed = currNode->nextseed;
+ while (currSeed != NULL)
+ {
+ if(currSeed == n){
+ precvSeed->nextseed = n->nextseed;
+ }
+ precvSeed = currSeed;
+ currSeed = currSeed->nextseed;
+ }
+ }
+ SYS_ARCH_UNPROTECT(lev);
+
+ if(n->role == NODE_ROLE_SERVER){
+ //node may have seed if it's under server mode
+ while(n->nextseed != NULL){
+ currSeed = n->nextseed;
+ // only tcp seed has its own socket, udp seed uses its server's
+ // so delete udp seed can't close socket which is used by server
+ if(currSeed->protocol == NODE_MODE_TCP && currSeed->sockfd != INVALID_SOCKET_ID){
+ close(currSeed->sockfd);
+ currSeed->sockfd = INVALID_SOCKET_ID;
+ }
+ // no task created for seed
+ //if(s->handletask != NULL)
+ // vTaskDelete(s->handletask);
+ n->nextseed = currSeed->nextseed;
+ currSeed->con_id = INVALID_CON_ID;
+ };
+ }
+
+ if(!((n->protocol == NODE_MODE_UDP)&&(n->role == NODE_ROLE_SEED))){
+ if(n->sockfd != INVALID_SOCKET_ID){
+ close(n->sockfd);
+ n->sockfd = INVALID_SOCKET_ID;
+ }
+ }
+ //task will exit itself in fail case
+ if(n->handletask){
+ vTaskDelete(n->handletask);
+ n->handletask = NULL;
+ }
+ n->con_id = INVALID_CON_ID;
+ return;
+}
+
+int hang_node(node* insert_node)
+{
+ node* n = mainlist;
+ SYS_ARCH_DECL_PROTECT(lev);
+ SYS_ARCH_PROTECT(lev);
+ while (n->next != NULL)
+ {
+ n = n->next;
+ if(insert_node->role == NODE_ROLE_SERVER) //need to check for server in case that two conns are binded to same port, because SO_REUSEADDR is enabled
+ {
+ if( (n->port == insert_node->port) && ((n->addr== insert_node->addr) && (n->role == insert_node->role) && (n->protocol == insert_node->protocol) ) ){
+ SYS_ARCH_UNPROTECT(lev);
+ struct in_addr addr;
+ addr.s_addr = htonl(insert_node->addr);
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "This conn(IP:%s PORT:%d) already exist",
+ inet_ntoa(addr),insert_node->port);
+ return -1;
+ }
+ }
+ }
+
+ n->next = insert_node;
+ SYS_ARCH_UNPROTECT(lev);
+ return 0;
+}
+
+int hang_seednode(node* main_node ,node* insert_node)
+{
+ node* n = main_node;
+
+ SYS_ARCH_DECL_PROTECT(lev);
+ SYS_ARCH_PROTECT(lev);
+ while (n->nextseed != NULL)
+ {
+ n = n->nextseed;
+ if( (n->port == insert_node->port) && (n->addr == insert_node->addr)){
+ SYS_ARCH_UNPROTECT(lev);
+ struct in_addr addr;
+ addr.s_addr = htonl(insert_node->addr);
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,
+ "This seed IP:%s PORT:%d already exist",
+ inet_ntoa(addr),insert_node->port);
+ return -1;
+ }
+ }
+
+ n->nextseed = insert_node;
+ SYS_ARCH_UNPROTECT(lev);
+ return 0;
+}
+
+node *seek_node(int con_id)
+{
+ node* n = mainlist;
+ while (n->next != NULL)
+ {
+ n = n->next;
+ if(n->con_id == con_id)
+ return n;
+
+ if(n->nextseed != NULL)
+ {
+ node* seed = n;
+ do{
+ seed = seed->nextseed;
+ if(seed->con_id == con_id)
+ return seed;
+ }while (seed->nextseed != NULL);
+ }
+ }
+ return NULL;
+}
+
+node *tryget_node(int n)
+{
+ SYS_ARCH_DECL_PROTECT(lev);
+ if ((n <= 0) || (n > NUM_NS)) {
+ return NULL;
+ }
+ SYS_ARCH_PROTECT(lev);
+ if (node_pool[n].con_id == INVALID_CON_ID || node_pool[n].sockfd == INVALID_SOCKET_ID) {
+ SYS_ARCH_UNPROTECT(lev);
+ return NULL;
+ }
+ SYS_ARCH_UNPROTECT(lev);
+ return &node_pool[n];
+}
+
+int atcmd_lwip_receive_data(node *curnode, u8 *buffer, u16 buffer_size, int *recv_size,
+ u8_t *udp_clientaddr, u16_t *udp_clientport){
+
+ struct timeval tv;
+ fd_set readfds;
+ int error_no = 0, ret = 0, size = 0;
+
+ FD_ZERO(&readfds);
+ FD_SET(curnode->sockfd, &readfds);
+ tv.tv_sec = RECV_SELECT_TIMEOUT_SEC;
+ tv.tv_usec = RECV_SELECT_TIMEOUT_USEC;
+ ret = select(curnode->sockfd + 1, &readfds, NULL, NULL, &tv);
+ if(!((ret > 0)&&(FD_ISSET(curnode->sockfd, &readfds))))
+ {
+ //AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,
+ // "[ATPR] No receive event for con_id %d", curnode->con_id);
+ goto exit;
+ }
+
+ if(curnode->protocol == NODE_MODE_UDP) //udp server receive from client
+ {
+ if(curnode->role == NODE_ROLE_SERVER){
+ //node * clinode;
+ struct sockaddr_in client_addr;
+ u32_t addr_len = sizeof(struct sockaddr_in);
+ memset((char *) &client_addr, 0, sizeof(client_addr));
+
+ if ((size = recvfrom(curnode->sockfd, buffer, buffer_size, 0, (struct sockaddr *) &client_addr, &addr_len)) > 0){
+ //at_printf("[ATPR]:%d,%s,%d,%s\r\n with packet_size: %d\r\n",con_id, inet_ntoa(client_addr.sin_addr.s_addr), ntohs(client_addr.sin_port), rx_buffer, packet_size);
+ //at_printf("\r\nsize: %d\r\n", recv_size);
+ //at_printf("%s", rx_buffer);
+ }
+ else{
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "[ATPR] ERROR:Failed to receive data");
+ error_no = 4;
+ }
+#if 0
+ clinode = create_node(NODE_MODE_UDP, NODE_ROLE_SEED);
+ clinode->sockfd = curnode->sockfd;
+ clinode->addr = ntohl(client_addr.sin_addr.s_addr);
+ clinode->port = ntohs(client_addr.sin_port);
+ if(hang_seednode(curnode,clinode) < 0){
+ delete_node(clinode);
+ clinode = NULL;
+ }
+#else
+ inet_ntoa_r(client_addr.sin_addr.s_addr, (char *)udp_clientaddr, 16);
+ *udp_clientport = ntohs(client_addr.sin_port);
+#endif
+ }
+ else{
+ struct sockaddr_in serv_addr;
+ u32_t addr_len = sizeof(struct sockaddr_in);
+ memset((char *) &serv_addr, 0, sizeof(serv_addr));
+ serv_addr.sin_family = AF_INET;
+ serv_addr.sin_port = htons(curnode->port);
+ serv_addr.sin_addr.s_addr = htonl(curnode->addr);
+
+ if ((size = recvfrom(curnode->sockfd, buffer, buffer_size, 0, (struct sockaddr *) &serv_addr, &addr_len)) > 0){
+ //at_printf("[ATPR]:%d,%s,%d,%s\r\n with packet_size: %d\r\n",con_id, inet_ntoa(serv_addr.sin_addr.s_addr), ntohs(serv_addr.sin_port), rx_buffer, packet_size);
+ //at_printf("\r\nsize: %d\r\n", recv_size);
+ //at_printf("%s", rx_buffer);
+ }
+ else{
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "[ATPR] ERROR:Failed to receive data");
+ error_no = 5;
+ }
+ }
+ }
+ else{
+ #if 0
+ if(curnode->role == NODE_ROLE_SERVER){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "[ATPR] ERROR: TCP Server must receive data from the seed");
+ error_no = 6;
+ }
+ #endif
+ //receive from seed or server
+ if((size = read(curnode->sockfd,buffer,buffer_size)) > 0)
+ {
+ //struct in_addr addr;
+ //addr.s_addr = htonl(curnode->addr);
+ //at_printf("[ATPR]:%d,%s,%d,%s\r\n with packet_size: %d\r\n",con_id, inet_ntoa(addr), curnode->port, rx_buffer, packet_size);
+ //at_printf("\r\nsize: %d\r\n", recv_size);
+ //at_printf("%s", rx_buffer);
+ }
+ else{
+ if(size == 0){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "[ATPR] ERROR:Connection is closed!");
+ error_no = 7;
+ }
+ else{
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "[ATPR] ERROR:Failed to receive data!");
+ error_no = 8;
+ }
+ }
+ }
+exit:
+ if(error_no == 0)
+ *recv_size = size;
+ else{
+ close(curnode->sockfd);
+ curnode->sockfd = INVALID_SOCKET_ID;
+ }
+ return error_no;
+}
+
+static void atcmd_lwip_receive_task(void *param)
+{
+
+ int i;
+ int packet_size = ETH_MAX_MTU;
+
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,
+ "Enter auto receive mode");
+
+ while(atcmd_lwip_is_autorecv_mode())
+ {
+ for (i = 0; i < NUM_NS; ++i) {
+ node* curnode = NULL;
+ int error_no = 0;
+ int recv_size = 0;
+ u8_t udp_clientaddr[16] = {0};
+ u16_t udp_clientport = 0;
+ curnode = tryget_node(i);
+ if(curnode == NULL)
+ continue;
+ if(curnode->protocol == NODE_MODE_TCP && curnode->role == NODE_ROLE_SERVER){
+ //TCP Server must receive data from the seed
+ continue;
+ }
+ error_no = atcmd_lwip_receive_data(curnode, rx_buffer, packet_size, &recv_size, udp_clientaddr, &udp_clientport);
+
+ if(atcmd_lwip_is_tt_mode()){
+ if((error_no == 0) && recv_size){
+ rx_buffer[recv_size] = '\0';
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,"Recv[%d]:%s", recv_size, rx_buffer);
+ at_print_data(rx_buffer, recv_size);
+ rtw_msleep_os(20);
+ }
+ continue;
+ }
+
+ if(error_no == 0){
+ if(recv_size){
+ #if CONFIG_LOG_SERVICE_LOCK
+ log_service_lock();
+ #endif
+ if(curnode->protocol == NODE_MODE_UDP && curnode->role == NODE_ROLE_SERVER){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,
+ "\r\n[ATPR] OK,%d,%d,%s,%d:", recv_size, curnode->con_id, udp_clientaddr, udp_clientport);
+ at_printf("\r\n[ATPR] OK,%d,%d,%s,%d:", recv_size, curnode->con_id, udp_clientaddr, udp_clientport);
+ }
+ else{
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,
+ "\r\n[ATPR] OK,%d,%d:",
+ recv_size,
+ curnode->con_id);
+ at_printf("\r\n[ATPR] OK,%d,%d:", recv_size, curnode->con_id);
+ }
+ at_print_data(rx_buffer, recv_size);
+ at_printf(STR_END_OF_ATCMD_RET);
+ #if CONFIG_LOG_SERVICE_LOCK
+ log_service_unlock();
+ #endif
+ }
+ }
+ else{
+ #if CONFIG_LOG_SERVICE_LOCK
+ log_service_lock();
+ #endif
+ at_printf("\r\n[ATPR] ERROR:%d,%d", error_no, curnode->con_id);
+ at_printf(STR_END_OF_ATCMD_RET);
+ #if CONFIG_LOG_SERVICE_LOCK
+ log_service_unlock();
+ #endif
+ }
+ }
+ }
+
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,
+ "Leave auto receive mode");
+
+ vTaskDelete(NULL);
+}
+
+int atcmd_lwip_start_autorecv_task(void){
+ atcmd_lwip_set_autorecv_mode(TRUE);
+ if(xTaskCreate(atcmd_lwip_receive_task, ((const char*)"atcmd_lwip_receive_task"), ATCP_STACK_SIZE, NULL, ATCMD_LWIP_TASK_PRIORITY, NULL) != pdPASS)
+ {
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "ERROR: Create receive task failed.");
+ atcmd_lwip_set_autorecv_mode(FALSE);
+ return -1;
+ }
+ return 0;
+}
+
+int atcmd_lwip_is_tt_mode(void){
+ return (atcmd_lwip_tt_mode == TRUE);
+}
+void atcmd_lwip_set_tt_mode(int enable){
+ atcmd_lwip_tt_mode = enable;
+}
+
+int atcmd_lwip_is_autorecv_mode(void){
+ return (atcmd_lwip_auto_recv == TRUE);
+}
+void atcmd_lwip_set_autorecv_mode(int enable){
+ atcmd_lwip_auto_recv = enable;
+}
+
+static void _tt_wait_rx_complete(){
+ s32 tick_current = rtw_get_current_time();
+
+ while(rtw_systime_to_ms(tick_current -atcmd_lwip_tt_lasttickcnt) < ATCMD_LWIP_TT_MAX_DELAY_TIME_MS ){
+ rtw_msleep_os(5);
+ tick_current = rtw_get_current_time();
+ }
+}
+
+static void atcmd_lwip_tt_handler(void* param)
+{
+ struct sockaddr_in cli_addr;
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,
+ "Enter TT data mode");
+ while(rtw_down_sema((_Sema *)&atcmd_lwip_tt_sema) == _SUCCESS) {
+ _lock lock;
+ _irqL irqL;
+ int tt_size = 0;
+ _tt_wait_rx_complete();
+
+ rtw_enter_critical(&lock, &irqL);
+ if((atcmd_lwip_tt_datasize >= 4) && (memcmp(log_buf, "----", 4) == 0)){
+ atcmd_lwip_set_tt_mode(FALSE);
+ atcmd_lwip_tt_datasize = 0;
+ rtw_exit_critical(&lock, &irqL);
+ break;
+ }
+ rtw_memcpy(tx_buffer, log_buf, atcmd_lwip_tt_datasize);
+ tt_size = atcmd_lwip_tt_datasize;
+ atcmd_lwip_tt_datasize = 0;
+ rtw_exit_critical(&lock, &irqL);
+ tx_buffer[tt_size] = '\0';
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,"Send[%d]:%s", tt_size, tx_buffer);
+ atcmd_lwip_send_data(mainlist->next, tx_buffer, tt_size, cli_addr);
+ }
+
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,
+ "Leave TT data mode");
+ rtw_free_sema((_Sema *)&atcmd_lwip_tt_sema);
+ atcmd_lwip_set_autorecv_mode(FALSE);
+ at_printf(STR_END_OF_ATCMD_RET); //mark return to command mode
+ vTaskDelete(NULL);
+}
+
+int atcmd_lwip_start_tt_task(void){
+ rtw_init_sema((_Sema *)&atcmd_lwip_tt_sema, 0);
+ atcmd_lwip_set_tt_mode(TRUE);
+ if(xTaskCreate(atcmd_lwip_tt_handler, ((const char*)"tt_hdl"), ATCP_STACK_SIZE, NULL, ATCMD_LWIP_TASK_PRIORITY, &atcmd_lwip_tt_task) != pdPASS){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,
+ "ERROR: Create tt task failed.");
+ goto err_exit;
+ }
+ rtw_msleep_os(20);
+ if(atcmd_lwip_is_autorecv_mode() != 1){
+ if(atcmd_lwip_start_autorecv_task()){
+ vTaskDelete(atcmd_lwip_tt_task);
+ goto err_exit;
+ }
+ }
+
+ return 0;
+
+err_exit:
+ atcmd_lwip_set_tt_mode(FALSE);
+ return -1;
+}
+
+void atcmd_lwip_erase_info(void){
+ atcmd_update_partition_info(AT_PARTITION_LWIP, AT_PARTITION_ERASE, NULL, 0);
+}
+
+int atcmd_lwip_write_info_to_flash(struct atcmd_lwip_conn_info *cur_conn, int enable)
+{
+ struct atcmd_lwip_conf read_data = {0};
+ int i = 0, found = 0;
+
+ atcmd_update_partition_info(AT_PARTITION_LWIP, AT_PARTITION_READ, (u8 *) &read_data, sizeof(struct atcmd_lwip_conf));
+
+ //fake that the conn exists already when disabling or there is no active conn on this moment
+ if(enable == 0){
+ atcmd_lwip_erase_info();
+ goto exit;
+ }
+
+ if(read_data.conn_num < 0 || read_data.conn_num > ATCMD_LWIP_CONN_STORE_MAX_NUM){
+ read_data.conn_num = 0;
+ read_data.last_index = -1;
+ }
+
+ for(i = 0; i < read_data.conn_num; i++){
+ if(memcmp((u8 *)cur_conn, (u8 *)&read_data.conn[i], sizeof(struct atcmd_lwip_conn_info)) == 0) {
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,
+ "the same profile found in flash");
+ found = 1;
+ break;
+ }
+ }
+
+ if(!found){
+ read_data.last_index++;
+ if(read_data.last_index >= ATCMD_LWIP_CONN_STORE_MAX_NUM)
+ read_data.last_index -= ATCMD_LWIP_CONN_STORE_MAX_NUM;
+ memcpy((u8 *)&read_data.conn[read_data.last_index], (u8 *)cur_conn, sizeof(struct atcmd_lwip_conn_info));
+ read_data.conn_num++;
+ if(read_data.conn_num > ATCMD_LWIP_CONN_STORE_MAX_NUM)
+ read_data.conn_num = ATCMD_LWIP_CONN_STORE_MAX_NUM;
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,
+ "not the same proto/addr/port, write new profile to flash");
+ }
+ if(!found || read_data.enable != enable){
+ read_data.enable = enable;
+ atcmd_update_partition_info(AT_PARTITION_LWIP, AT_PARTITION_WRITE, (u8 *) &read_data, sizeof(struct atcmd_lwip_conf));
+ }
+exit:
+ return 0;
+}
+
+int atcmd_lwip_read_info_from_flash(u8 *read_data, u32 read_len)
+{
+ atcmd_update_partition_info(AT_PARTITION_LWIP, AT_PARTITION_READ, read_data, read_len);
+ return 0;
+}
+
+int atcmd_lwip_auto_connect(void)
+{
+ struct atcmd_lwip_conf read_data = {0};
+ struct atcmd_lwip_conn_info *re_conn;
+ node* re_node = NULL;
+ int i, error_no = 0;
+ int last_index;
+
+ atcmd_lwip_read_info_from_flash((u8 *)&read_data, sizeof(struct atcmd_lwip_conf));
+ if(read_data.enable == 0){
+ error_no = 1;
+ goto exit;
+ }
+ if(read_data.conn_num > ATCMD_LWIP_CONN_STORE_MAX_NUM || read_data.conn_num <= 0){
+ error_no = 2;
+ goto exit;
+ }
+
+ last_index = read_data.last_index;
+ for(i = 0; i < read_data.conn_num; i++){
+ re_conn = &read_data.conn[last_index];
+ last_index ++;
+ if(last_index >= ATCMD_LWIP_CONN_STORE_MAX_NUM)
+ last_index -= ATCMD_LWIP_CONN_STORE_MAX_NUM;
+ re_node = create_node(re_conn->protocol, re_conn->role);
+ if(re_node == NULL){
+ error_no = 3;
+ break;
+ }
+ re_node->addr = re_conn->remote_addr;
+ re_node->port = re_conn->remote_port;
+ re_node->local_addr = re_conn->local_addr;
+ re_node->local_port = re_conn->local_port;
+ if(re_node->protocol == NODE_MODE_UDP)
+ re_node->sockfd = socket(AF_INET,SOCK_DGRAM,0);
+ else
+ re_node->sockfd = socket(AF_INET, SOCK_STREAM, 0);
+
+ if (re_node->sockfd == INVALID_SOCKET_ID) {
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,"Failed to create sock_fd!");
+ error_no = 4;
+ break;
+ }
+
+ struct in_addr addr;
+ addr.s_addr = htonl(re_node->addr);
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,
+ "\r\nTry connect: %d,%d,%s,%d",
+ re_node->sockfd, re_node->protocol,
+ inet_ntoa(addr), re_node->port);
+
+ if(re_node->role == NODE_ROLE_SERVER){
+ //TODO: start server here
+ goto exit;
+ }
+
+ if (re_node->protocol == NODE_MODE_TCP){//TCP MODE
+ struct sockaddr_in c_serv_addr;
+ memset(&c_serv_addr, 0, sizeof(c_serv_addr));
+ c_serv_addr.sin_family = AF_INET;
+ c_serv_addr.sin_addr.s_addr = htonl(re_node->addr);
+ c_serv_addr.sin_port = htons(re_node->port);
+ if(connect(re_node->sockfd, (struct sockaddr *)&c_serv_addr, sizeof(c_serv_addr)) == 0){
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,"Connect to Server successful!");
+ if(hang_node(re_node) < 0){
+ error_no = 5;
+ }
+ break;
+ }else{
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,"Connect to Server failed(%d)!", errno);
+ error_no = 6;
+ delete_node(re_node);
+ re_node = NULL;
+ continue; //try next conn
+ }
+ }
+ else{
+ if(re_node->local_port){
+ struct sockaddr_in addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family=AF_INET;
+ addr.sin_port=htons(re_node->local_port);
+ addr.sin_addr.s_addr=htonl(INADDR_ANY) ;
+ if (bind(re_node->sockfd, (struct sockaddr *)&addr, sizeof(addr))<0) {
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,"bind sock error!");
+ error_no = 7;
+ delete_node(re_node);
+ re_node = NULL;
+ continue;
+ }
+ }
+ if(hang_node(re_node) < 0){
+ error_no = 8;
+ }
+ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,"UDP client starts successful!");
+ break;
+ }
+ }
+
+exit:
+ if(re_node && error_no)
+ delete_node(re_node);
+ return error_no;
+}
+
+int atcmd_lwip_restore_from_flash(void){
+ int ret = -1;
+ if(atcmd_lwip_auto_connect() == 0){
+ if(atcmd_lwip_start_tt_task() == 0)
+ ret = 0;
+ }
+ return ret;
+}
+#endif
+
+//------------------------------------------------------------ Add pvvx Lwip Info
+/* Get one byte from the 4-byte address */
+#define ip4_addr1(ipaddr) (((u8_t*)(ipaddr))[0])
+#define ip4_addr2(ipaddr) (((u8_t*)(ipaddr))[1])
+#define ip4_addr3(ipaddr) (((u8_t*)(ipaddr))[2])
+#define ip4_addr4(ipaddr) (((u8_t*)(ipaddr))[3])
+/* These are cast to u16_t, with the intent that they are often arguments
+ * to printf using the U16_F format from cc.h. */
+#define ip4_addr1_16(ipaddr) ((u16_t)ip4_addr1(ipaddr))
+#define ip4_addr2_16(ipaddr) ((u16_t)ip4_addr2(ipaddr))
+#define ip4_addr3_16(ipaddr) ((u16_t)ip4_addr3(ipaddr))
+#define ip4_addr4_16(ipaddr) ((u16_t)ip4_addr4(ipaddr))
+
+#define IP2STR(ipaddr) ip4_addr1_16(ipaddr), \
+ ip4_addr2_16(ipaddr), \
+ ip4_addr3_16(ipaddr), \
+ ip4_addr4_16(ipaddr)
+
+#define IPSTR "%d.%d.%d.%d"
+
+extern const char * const tcp_state_str[];
+/*
+static const char * const tcp_state_str[] = {
+ "CLOSED",
+ "LISTEN",
+ "SYN_SENT",
+ "SYN_RCVD",
+ "ESTABLISHED",
+ "FIN_WAIT_1",
+ "FIN_WAIT_2",
+ "CLOSE_WAIT",
+ "CLOSING",
+ "LAST_ACK",
+ "TIME_WAIT"
+};
+*/
+/******************************************************************************
+ * FunctionName : debug
+ * Parameters :
+ * Returns :
+*******************************************************************************/
+void print_udp_pcb(void)
+{
+ struct udp_pcb *pcb;
+ bool prt_none = true;
+ rtl_printf("UDP pcbs:\n");
+ for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
+ rtl_printf("flg:%02x\t" IPSTR ":%d\t" IPSTR ":%d\trecv:%p\n", pcb->flags, IP2STR(&pcb->local_ip), pcb->local_port, IP2STR(&pcb->remote_ip), pcb->remote_port, pcb->recv );
+ prt_none = false;
+ }
+ if(prt_none) rtl_printf("none\n");
+}
+/******************************************************************************
+ * FunctionName : debug
+ * Parameters :
+ * Returns :
+*******************************************************************************/
+void print_tcp_pcb(void)
+{
+ struct tcp_pcb *pcb;
+ rtl_printf("Active PCB states:\n");
+ bool prt_none = true;
+ for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
+ rtl_printf("Port %d|%d\tflg:%02x\ttmr:%p\t%s\n", pcb->local_port, pcb->remote_port, pcb->flags, pcb->tmr, tcp_state_str[pcb->state]);
+ prt_none = false;
+ }
+ if(prt_none) rtl_printf("none\n");
+ rtl_printf("Listen PCB states:\n");
+ prt_none = true;
+ for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) {
+ rtl_printf("Port %d|%d\tflg:%02x\ttmr:%p\t%s\n", pcb->local_port, pcb->remote_port, pcb->flags, pcb->tmr, tcp_state_str[pcb->state]);
+ prt_none = false;
+ }
+ if(prt_none) rtl_printf("none\n");
+ rtl_printf("TIME-WAIT PCB states:\n");
+ prt_none = true;
+ for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
+ rtl_printf("Port %d|%d\tflg:%02x\ttmr:%p\t%s\n", pcb->local_port, pcb->remote_port, pcb->flags, pcb->tmr, tcp_state_str[pcb->state]);
+ prt_none = false;
+ }
+ if(prt_none) rtl_printf("none\n");
+}
+/******************************************************************************
+ * FunctionName : debug
+ * Parameters :
+ * Returns :
+*******************************************************************************/
+void print_netif(int inum)
+{
+ rtl_printf("Net Info[%d]: " IPSTR, inum, IP2STR(&xnetif[inum].ip_addr));
+ rtl_printf(", " IPSTR ", " IPSTR "\n", IP2STR(&xnetif[inum].netmask), IP2STR(&xnetif[inum].gw));
+}
+/******************************************************************************
+ * FunctionName : debug
+ * Parameters :
+ * Returns :
+*******************************************************************************/
+//------------------------------------------------------------------------------
+void fATPx(void *arg) // Info Lwip
+{
+ printf("=== LwIP Info ===\n");
+ print_netif(0);
+ print_netif(1);
+ print_udp_pcb();
+ print_tcp_pcb();
+}
+//------------------------------------------------------------ Add pvvx end
+#if CONFIG_TRANSPORT
+log_item_t at_transport_items[ ] = {
+#if ATCMD_VER == ATVER_1
+ {"ATP1", fATP1,},//mode TCP=0,UDP=1
+ {"ATP2", fATP2,},//LOCAL PORT
+ {"ATP3", fATP3,},//REMOTE IP
+ {"ATP4", fATP4,},//REMOTE PORT
+ {"ATP5", fATP5,},//START SERVER
+ {"ATP6", fATP6,},//START CLIENT
+ {"ATP?", fATPZ,},//SETTING
+ {"ATR0", fATR0,},//READ DATA
+ {"ATR1", fATR1,},//SET PACKET SIZE
+ {"ATRA", fATRA,},//WRITE DATA
+ {"ATRB", fATRB,},//SET WRITE PACKET SIZE
+#endif
+#if ATCMD_VER == ATVER_2
+ {"ATP0", fATP0,},//query errno if defined
+ {"ATPS", fATPS,},//Create Server
+ {"ATPD", fATPD,},//Close Server/Client connection
+ {"ATPC", fATPC,},//Create Client
+ {"ATPT", fATPT,},//WRITE DATA
+ {"ATPR", fATPR,},//READ DATA
+ {"ATPK", fATPK,},//Auto recv
+ {"ATPP", fATPP,},//PING
+ {"ATPI", fATPI,},//printf connection status
+ {"ATPU", fATPU,}, //transparent transmission mode
+ {"ATPL", fATPL,}, //lwip auto reconnect setting
+#endif
+ {"ATP?", fATPx,}, //Lwip pcb Info
+};
+
+#if ATCMD_VER == ATVER_2
+void print_tcpip_at(void *arg){
+ int index;
+ int cmd_len = 0;
+
+ cmd_len = sizeof(at_transport_items)/sizeof(at_transport_items[0]);
+ for(index = 0; index < cmd_len; index++)
+ at_printf("\r\n%s", at_transport_items[index].log_cmd);
+}
+#endif
+
+void at_transport_init(void)
+{
+#if ATCMD_VER == ATVER_2
+ init_node_pool();
+ mainlist = create_node(-1,-1);
+#endif
+ log_service_add_table(at_transport_items, sizeof(at_transport_items)/sizeof(at_transport_items[0]));
+}
+
+log_module_init(at_transport_init);
+#endif
+#endif //#ifdef CONFIG_AT_LWIP
diff --git a/RTLGDB/USDK/component/common/api/at_cmd/atcmd_lwip.h b/RTLGDB/USDK/component/common/api/at_cmd/atcmd_lwip.h
new file mode 100644
index 0000000..bbdb35c
--- /dev/null
+++ b/RTLGDB/USDK/component/common/api/at_cmd/atcmd_lwip.h
@@ -0,0 +1,100 @@
+#ifndef __ATCMD_LWIP_H__
+#define __ATCMD_LWIP_H__
+
+#include
+#ifdef CONFIG_AT_LWIP
+
+#include "main.h"
+#include
+#include "lwip/sockets.h"
+#include "lwip/api.h"
+#include "lwip/sys.h"
+#include "lwip/igmp.h"
+#include "lwip/inet.h"
+#include "lwip/tcp.h"
+#include "lwip/raw.h"
+#include "lwip/udp.h"
+#include "lwip/tcpip.h"
+#include "lwip/pbuf.h"
+#include "lwip/netdb.h"
+#include "lwip_netconf.h"
+
+
+#define _AT_TRANSPORT_MODE_ "ATP1"
+#define _AT_TRANSPORT_LOCAL_PORT_ "ATP2"
+#define _AT_TRANSPORT_REMOTE_IP_ "ATP3"
+#define _AT_TRANSPORT_REMOTE_PORT_ "ATP4"
+#define _AT_TRANSPORT_START_SERVER_ "ATP5"
+#define _AT_TRANSPORT_START_CLIENT_ "ATP6"
+#define _AT_TRANSPORT_SHOW_SETTING_ "ATP?"
+#define _AT_TRANSPORT_RECEIVE_DATA_ "ATR0"
+#define _AT_TRANSPORT_RECEIVE_PACKET_SIZE_ "ATR1"
+#define _AT_TRANSPORT_WRITE_DATA_ "ATRA"
+#define _AT_TRANSPORT_WRITE_PACKET_SIZE_ "ATRB"
+
+#define NODE_MODE_TCP 0
+#define NODE_MODE_UDP 1
+
+#define NODE_ROLE_SERVER 0
+#define NODE_ROLE_CLIENT 1
+#define NODE_ROLE_SEED 2
+
+#define INVALID_SOCKET_ID (-1)
+
+//parameters
+#ifndef NET_IF_NUM
+#define NET_IF_NUM 2
+#endif
+
+#define ATCMD_LWIP_TASK_PRIORITY (tskIDLE_PRIORITY + 1)
+
+#if ATCMD_VER == ATVER_2
+
+#define SERVER "127.0.0.1"
+
+#define NUM_NS (MEMP_NUM_NETCONN) //maximum number of node and seed, same as NUM_SOCKETS
+
+#define ETH_MAX_MTU 1500
+
+#define INVALID_CON_ID (-1)
+
+#define RECV_SELECT_TIMEOUT_SEC (0)
+#define RECV_SELECT_TIMEOUT_USEC (20000) //20ms
+
+typedef struct ns
+{
+ int con_id;
+ int sockfd;
+ s8_t role;
+ int protocol;
+ u32_t addr;
+ u16_t port;
+ u32_t local_addr;
+ u16_t local_port;
+ xTaskHandle handletask;
+ struct ns* next;
+ struct ns* nextseed;
+} node;
+
+extern xTaskHandle atcmd_lwip_tt_task;
+extern xSemaphoreHandle atcmd_lwip_tt_sema;
+extern volatile int atcmd_lwip_tt_datasize;
+extern volatile int atcmd_lwip_tt_lasttickcnt;
+#define ATCMD_LWIP_TT_MAX_DELAY_TIME_MS (20) //transparent transmission interval
+
+extern int atcmd_lwip_is_tt_mode(void);
+extern void atcmd_lwip_set_tt_mode(int enable);
+int atcmd_lwip_send_data(node *curnode, u8 *data, u16 data_sz, struct sockaddr_in cli_addr);
+int atcmd_lwip_receive_data(node *curnode, u8 *buffer, u16 buffer_size, int *recv_size,
+ u8_t *udp_clientaddr, u16_t *udp_clientport);
+node* create_node(int mode, s8_t role);
+void init_node_pool(void);
+void delete_node(node *n);
+int hang_node(node* insert_node);
+int hang_seednode(node* main_node ,node* insert_node);
+node *seek_node(int con_id);
+node *tryget_node(int n);
+#endif
+
+#endif //#ifdef CONFIG_AT_LWIP
+#endif //#ifndef __ATCMD_LWIP_H__
diff --git a/RTLGDB/USDK/component/common/api/at_cmd/atcmd_mp.c b/RTLGDB/USDK/component/common/api/at_cmd/atcmd_mp.c
new file mode 100644
index 0000000..d10bf07
--- /dev/null
+++ b/RTLGDB/USDK/component/common/api/at_cmd/atcmd_mp.c
@@ -0,0 +1,195 @@
+#include
+#include
+#include
+#include "log_service.h"
+#include "atcmd_mp.h"
+
+#if CONFIG_ATCMD_MP_EXT0
+ extern void fATM0(void *arg); // MP ext0 AT command
+#endif
+
+#if CONFIG_ATCMD_MP
+//-------- AT MP commands ---------------------------------------------------------------
+void fATMG(void *arg)
+{
+ gpio_t gpio_test;
+ int argc = 0, val, cnts, i, write=0, data=0;
+ char *argv[MAX_ARGC] = {0}, port, num;
+ PinName pin = NC;
+ u32 tConfigDebugInfo = ConfigDebugInfo;
+
+ AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "[ATMG]: _AT_MP_GPIO_TEST_");
+ if(!arg){
+ AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "[ATMG] Usage: ATSG=w,PINNAMES(ex:A0B1C2...),VALUE(0/1)");
+ AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "[ATMG] Usage: ATSG=r,PINNAMES(ex:A0B1C2...)");
+ return;
+ }
+
+ argc = parse_param(arg, argv);
+ cnts = strlen(argv[2]);
+ if(cnts % 2) return;
+ cnts /= 2;
+ if(cnts == 0) return;
+
+ if(strcmp(argv[1], "w") == 0){
+ write = 1;
+ if(strcmp(argv[3], "1") == 0)
+ data = 1;
+ }
+ // Remove debug info massage
+ _AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "[ATMG] %s: ", argv[1]);
+ ConfigDebugInfo = 0;
+ for(i=0; i<(cnts*2); i+=2){
+ pin = NC;
+ port = argv[2][i];
+ num = argv[2][i+1];
+ if(port >= 'a' && port <= 'z')
+ port -= ('a' - 'A');
+ if(num >= 'a' && num <= 'z')
+ num -= ('a' - 'A');
+ switch(port){
+ case 'A':
+ switch(num){
+ case '0': pin = PA_0; break; case '1': pin = PA_1; break; case '2': pin = PA_2; break; case '3': pin = PA_3; break;
+ case '4': pin = PA_4; break; case '5': pin = PA_5; break; case '6': pin = PA_6; break; case '7': pin = PA_7; break;
+ }
+ break;
+ case 'B':
+ switch(num){
+ case '0': pin = PB_0; break; case '1': pin = PB_1; break; case '2': pin = PB_2; break; case '3': pin = PB_3; break;
+ case '4': pin = PB_4; break; case '5': pin = PB_5; break; case '6': pin = PB_6; break; case '7': pin = PB_7; break;
+ }
+ break;
+ case 'C':
+ switch(num){
+ case '0': pin = PC_0; break; case '1': pin = PC_1; break; case '2': pin = PC_2; break; case '3': pin = PC_3; break;
+ case '4': pin = PC_4; break; case '5': pin = PC_5; break; case '6': pin = PC_6; break; case '7': pin = PC_7; break;
+ case '8': pin = PC_8; break; case '9': pin = PC_9; break;
+ }
+ break;
+ case 'D':
+ switch(num){
+ case '0': pin = PD_0; break; case '1': pin = PD_1; break; case '2': pin = PD_2; break; case '3': pin = PD_3; break;
+ case '4': pin = PD_4; break; case '5': pin = PD_5; break; case '6': pin = PD_6; break; case '7': pin = PD_7; break;
+ case '8': pin = PD_8; break; case '9': pin = PD_9; break;
+ }
+ break;
+ case 'E':
+ switch(num){
+ case '0': pin = PE_0; break; case '1': pin = PE_1; break; case '2': pin = PE_2; break; case '3': pin = PE_3; break;
+ case '4': pin = PE_4; break; case '5': pin = PE_5; break; case '6': pin = PE_6; break; case '7': pin = PE_7; break;
+ case '8': pin = PE_8; break; case '9': pin = PE_9; break; case 'A': pin = PE_A; break;
+ }
+ break;
+ case 'F':
+ switch(num){
+ case '0': pin = PF_0; break; case '1': pin = PF_1; break; case '2': pin = PF_2; break; case '3': pin = PF_3; break;
+ case '4': pin = PF_4; break; case '5': pin = PF_5; break;
+ }
+ break;
+ case 'G':
+ switch(num){
+ case '0': pin = PG_0; break; case '1': pin = PG_1; break; case '2': pin = PG_2; break; case '3': pin = PG_3; break;
+ case '4': pin = PG_4; break; case '5': pin = PG_5; break; case '6': pin = PG_6; break; case '7': pin = PG_7; break;
+ }
+ break;
+ case 'H':
+ switch(num){
+ case '0': pin = PH_0; break; case '1': pin = PH_1; break; case '2': pin = PH_2; break; case '3': pin = PH_3; break;
+ case '4': pin = PH_4; break; case '5': pin = PH_5; break; case '6': pin = PH_6; break; case '7': pin = PH_7; break;
+ }
+ break;
+ case 'I':
+ switch(num){
+ case '0': pin = PI_0; break; case '1': pin = PI_1; break; case '2': pin = PI_2; break; case '3': pin = PI_3; break;
+ case '4': pin = PI_4; break; case '5': pin = PI_5; break; case '6': pin = PI_6; break; case '7': pin = PI_7; break;
+ }
+ break;
+ case 'J':
+ switch(num){
+ case '0': pin = PJ_0; break; case '1': pin = PJ_1; break; case '2': pin = PJ_2; break; case '3': pin = PJ_3; break;
+ case '4': pin = PJ_4; break; case '5': pin = PJ_5; break; case '6': pin = PJ_6; break;
+ }
+ break;
+ case 'K':
+ switch(num){
+ case '0': pin = PK_0; break; case '1': pin = PK_1; break; case '2': pin = PK_2; break; case '3': pin = PK_3; break;
+ case '4': pin = PK_4; break; case '5': pin = PK_5; break; case '6': pin = PK_6; break;
+ }
+ break;
+ }
+ if(pin == NC){
+ _AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "X,");
+ continue;
+ }
+ // Initial input control pin
+ gpio_init(&gpio_test, pin);
+ if(write){
+ gpio_dir(&gpio_test, PIN_OUTPUT); // Direction: Output
+ gpio_mode(&gpio_test, PullNone); // No pull
+ gpio_write(&gpio_test, data);
+ _AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "%d,", data);
+ }else{
+ gpio_dir(&gpio_test, PIN_INPUT); // Direction: Input
+ gpio_mode(&gpio_test, PullUp); // Pull-High
+ val = gpio_read(&gpio_test);
+ _AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "%d,", val);
+ }
+ }
+ _AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "\n");
+ // Recover debug info massage
+ ConfigDebugInfo = tConfigDebugInfo;
+}
+
+void fATMR(void *arg)
+{
+ u32 idx;
+
+ AT_PRINTK("[ATMR]: _AT_MP_SDR_TEST_");
+#ifdef CONFIG_SDR_EN
+ for (idx = 0; idx < 0x200000; idx = idx+4){
+ HAL_WRITE32(0x30000000, idx, 0x12345678);
+ if (HAL_READ32(0x30000000, idx) != 0x12345678) {
+ AT_PRINTK("[ATMR]: SDR test fail addr 0x08x, value 0x08%x",(0x30000000+idx),HAL_READ32(0x30000000, idx));
+ return;
+ }
+ }
+ AT_PRINTK("[ATMR]: SDR test success");
+#endif
+}
+
+void fATMt(void *arg)
+{
+ int argc = 0;
+ char *argv[MAX_ARGC] = {0};
+
+ AT_PRINTK("[ATM#]: _AT_MP_TEST_");
+ argc = parse_param(arg, argv);
+}
+
+void fATMx(void *arg)
+{
+ AT_PRINTK("[ATM?]: _AT_MP_HELP_");
+}
+
+log_item_t at_mp_items[] = {
+ {"ATMG", fATMG,}, // MP GPIO test
+ {"ATMR", fATMR,}, // MP SDR test
+ {"ATM#", fATMt,}, // test command
+ {"ATM?", fATMx,}, // Help
+#if CONFIG_ATCMD_MP_EXT0
+ {"ATM0", fATM0,}, // MP ext0 AT command
+#endif
+};
+
+void at_mp_init(void)
+{
+ log_service_add_table(at_mp_items, sizeof(at_mp_items)/sizeof(at_mp_items[0]));
+}
+
+#if SUPPORT_LOG_SERVICE
+log_module_init(at_mp_init);
+#endif
+
+#endif // #if CONFIG_ATCMD_MP
+
diff --git a/RTLGDB/USDK/component/common/api/at_cmd/atcmd_mp.h b/RTLGDB/USDK/component/common/api/at_cmd/atcmd_mp.h
new file mode 100644
index 0000000..1b2d774
--- /dev/null
+++ b/RTLGDB/USDK/component/common/api/at_cmd/atcmd_mp.h
@@ -0,0 +1,12 @@
+#ifndef __ATCMD_MP_H__
+#define __ATCMD_MP_H__
+
+#define CONFIG_ATCMD_MP_EXT0 0 //support MP ext0 AT command
+
+typedef struct _at_command_mp_ext_item_{
+ char *mp_ext_cmd;
+ int (*mp_ext_fun)(void **argv, int argc);
+ char *mp_ext_usage;
+}at_mp_ext_item_t;
+
+#endif
diff --git a/RTLGDB/USDK/component/common/api/at_cmd/atcmd_sys.c b/RTLGDB/USDK/component/common/api/at_cmd/atcmd_sys.c
new file mode 100644
index 0000000..01ea88c
--- /dev/null
+++ b/RTLGDB/USDK/component/common/api/at_cmd/atcmd_sys.c
@@ -0,0 +1,1434 @@
+#include
+#ifdef CONFIG_AT_SYS
+
+#include "platform_stdlib.h"
+//#include "platform_autoconf.h"
+//#include "main.h"
+#include "autoconf.h"
+#include "hal_adc.h"
+#include "gpio_api.h" // mbed
+#include "sys_api.h"
+#include "rtl8195a.h"
+#include "flash_api.h"
+#include "rtl_lib.h"
+#include "build_info.h"
+#include "analogin_api.h"
+#include "log_service.h"
+#include "atcmd_sys.h"
+#include "osdep_api.h"
+#include "atcmd_wifi.h"
+#include "tcm_heap.h"
+#if CONFIG_OTA_UPDATE
+#include "update.h"
+#endif
+
+#ifndef ATCMD_VER
+#define ATVER_1 1
+#define ATVER_2 2
+#define ATCMD_VER ATVER_2
+#if CONFIG_EXAMPLE_UART_ATCMD
+#define ATCMD_VER ATVER_2
+#else
+#define ATCMD_VER ATVER_1
+#endif
+#endif
+
+#if defined(configUSE_WAKELOCK_PMU) && (configUSE_WAKELOCK_PMU == 1)
+#include "freertos_pmu.h"
+#endif
+
+extern u32 ConfigDebugErr;
+extern u32 ConfigDebugInfo;
+extern u32 ConfigDebugWarn;
+extern u32 CmdDumpWord(IN u16 argc, IN u8 *argv[]);
+extern u32 CmdWriteWord(IN u16 argc, IN u8 *argv[]);
+#if CONFIG_UART_XMODEM
+extern void OTU_FW_Update(u8, u8, u32);
+#endif
+
+struct _dev_id2name {
+ u8 id;
+ u8 *name;
+};
+
+struct _dev_id2name dev_id2name[] = { { UART0, "UART0" }, { UART1, "UART1" }, {
+UART2, "UART2" }, { SPI0, "SPI0" }, { SPI1, "SPI1" }, { SPI2, "SPI2" }, {
+SPI0_MCS, "SPI0_MCS" }, { I2C0, "I2C0" }, { I2C1, "I2C1" }, { I2C2, "I2C2" }, {
+I2C3, "I2C3" }, { I2S0, "I2S0" }, { I2S1, "I2S1" }, { PCM0, "PCM0" }, {
+PCM1, "PCM1" }, { ADC0, "ADC0" }, { DAC0, "DAC0" }, { DAC1, "DAC1" }, {
+SDIOD, "SDIOD" }, { SDIOH, "SDIOH" }, { USBOTG, "USBOTG" }, { MII, "MII" }, {
+WL_LED, "WL_LED" }, { WL_ANT0, "WL_ANT0" }, { WL_ANT1, "WL_ANT1" }, {
+WL_BTCOEX, "WL_BTCOEX" }, { WL_BTCMD, "WL_BTCMD" }, { NFC, "NFC" }, {
+PWM0, "PWM0" }, { PWM1, "PWM1" }, { PWM2, "PWM2" }, { PWM3, "PWM3" }, {
+ETE0, "ETE0" }, { ETE1, "ETE1" }, { ETE2, "ETE2" }, { ETE3, "ETE3" }, {
+EGTIM, "EGTIM" }, { SPI_FLASH, "SPI_FLASH" }, { SDR, "SDR" }, { JTAG, "JTAG" },
+ { TRACE, "TRACE" }, { LOG_UART, "LOG_UART" }, {
+ LOG_UART_IR, "LOG_UART_IR" }, { SIC, "SIC" }, { EEPROM, "EEPROM" }, {
+ DEBUG, "DEBUG" }, { 255, "" } };
+
+void fATSI(void *arg) {
+ uint32 x = 0;
+ int i;
+ u8 * s;
+ for (i = 0; dev_id2name[i].id != 255; i++) {
+ ReadHWPwrState(dev_id2name[i].id, &x);
+ s = "?";
+ switch (x) {
+ case HWACT:
+ s = "ACT";
+ break;
+ case HWCG:
+ s = "CG";
+ break;
+ case HWINACT:
+ s = "WACT";
+ break;
+ case UNDEF:
+ s = "UNDEF";
+ break;
+ case ALLMET:
+ s = "ALLMET";
+ break;
+ }
+ printf("Dev %s, state = %s\n", dev_id2name[i].name, s);
+ }
+ for (i = 0; i < _PORT_MAX; i++)
+ printf("Port %c state: 0x%04x\n", i + 'A', GPIOState[i]);
+}
+
+//-------- AT SYS commands ---------------------------------------------------------------
+void fATSD(void *arg) {
+ int argc = 0;
+ char *argv[MAX_ARGC] = { 0 };
+ AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS,
+ "[ATSD]: _AT_SYSTEM_DUMP_REGISTER_");
+ if (!arg) {
+ AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSD] Usage: ATSD=REGISTER");
+ return;
+ }
+ argc = parse_param(arg, argv);
+ if (argc == 2 || argc == 3)
+ CmdDumpWord(argc - 1, (unsigned char**) (argv + 1));
+}
+
+#if ATCMD_VER == ATVER_2
+void fATXD(void *arg) {
+ int argc = 0;
+ char *argv[MAX_ARGC] = { 0 };
+
+ AT_DBG_MSG(AT_FLAG_EDIT, AT_DBG_ALWAYS,
+ "[ATXD]: _AT_SYSTEM_WRITE_REGISTER_");
+ if (!arg) {
+ AT_DBG_MSG(AT_FLAG_EDIT, AT_DBG_ALWAYS,
+ "[ATXD] Usage: ATXD=REGISTER,VALUE");
+ return;
+ }
+ argc = parse_param(arg, argv);
+ if (argc == 3)
+ CmdWriteWord(argc - 1, (unsigned char**) (argv + 1));
+}
+#endif
+
+#if ATCMD_VER == ATVER_1
+
+void fATSC(void *arg)
+{
+ AT_DBG_MSG(AT_FLAG_OTA, AT_DBG_ALWAYS, "[ATSC]: _AT_SYSTEM_CLEAR_OTA_SIGNATURE_");
+ sys_clear_ota_signature();
+}
+
+void fATSR(void *arg)
+{
+ AT_DBG_MSG(AT_FLAG_OTA, AT_DBG_ALWAYS, "[ATSR]: _AT_SYSTEM_RECOVER_OTA_SIGNATURE_");
+ sys_recover_ota_signature();
+}
+
+#if CONFIG_UART_XMODEM
+void fATSY(void *arg)
+{
+ if (HalGetChipId() < CHIP_ID_8195AM) {
+ OTU_FW_Update(0, 0, 115200);
+ } else {
+ // use xmodem to update, RX: PA_6, TX: PA_7, baudrate: 1M
+ OTU_FW_Update(0, 2, 115200);
+ }
+}
+#endif
+
+#if SUPPORT_MP_MODE
+void fATSA(void *arg)
+{
+ u32 tConfigDebugInfo = ConfigDebugInfo;
+ int argc = 0, channel;
+ char *argv[MAX_ARGC] = {0}, *ptmp;
+ u16 offset, gain;
+
+ AT_DBG_MSG(AT_FLAG_ADC, AT_DBG_ALWAYS, "[ATSA]: _AT_SYSTEM_ADC_TEST_");
+ if(!arg) {
+ AT_DBG_MSG(AT_FLAG_ADC, AT_DBG_ALWAYS, "[ATSA] Usage: ATSA=CHANNEL(0~2)");
+ AT_DBG_MSG(AT_FLAG_ADC, AT_DBG_ALWAYS, "[ATSA] Usage: ATSA=k_get");
+ AT_DBG_MSG(AT_FLAG_ADC, AT_DBG_ALWAYS, "[ATSA] Usage: ATSA=k_set[offet(hex),gain(hex)]");
+ return;
+ }
+
+ argc = parse_param(arg, argv);
+ if(strcmp(argv[1], "k_get") == 0) {
+ sys_adc_calibration(0, &offset, &gain);
+// AT_DBG_MSG(AT_FLAG_ADC, AT_DBG_ALWAYS, "[ATSA] offset = 0x%04X, gain = 0x%04X", offset, gain);
+ } else if(strcmp(argv[1], "k_set") == 0) {
+ if(argc != 4) {
+ AT_DBG_MSG(AT_FLAG_ADC, AT_DBG_ALWAYS, "[ATSA] Usage: ATSA=k_set[offet(hex),gain(hex)]");
+ return;
+ }
+ offset = strtoul(argv[2], &ptmp, 16);
+ gain = strtoul(argv[3], &ptmp, 16);
+ sys_adc_calibration(1, &offset, &gain);
+// AT_DBG_MSG(AT_FLAG_ADC, AT_DBG_ALWAYS, "[ATSA] offset = 0x%04X, gain = 0x%04X", offset, gain);
+ } else {
+ channel = atoi(argv[1]);
+ if(channel < 0 || channel > 2) {
+ AT_DBG_MSG(AT_FLAG_ADC, AT_DBG_ALWAYS, "[ATSA] Usage: ATSA=CHANNEL(0~2)");
+ return;
+ }
+ analogin_t adc;
+ u16 adcdat;
+
+ // Remove debug info massage
+ ConfigDebugInfo = 0;
+ if(channel == 0)
+ analogin_init(&adc, AD_1);
+ else if(channel == 1)
+ analogin_init(&adc, AD_2);
+ else
+ analogin_init(&adc, AD_3);
+ adcdat = analogin_read_u16(&adc)>>4;
+ analogin_deinit(&adc);
+ // Recover debug info massage
+ ConfigDebugInfo = tConfigDebugInfo;
+
+ AT_DBG_MSG(AT_FLAG_ADC, AT_DBG_ALWAYS, "[ATSA] A%d = 0x%04X", channel, adcdat);
+ }
+}
+
+void fATSG(void *arg)
+{
+ gpio_t gpio_test;
+ int argc = 0, val;
+ char *argv[MAX_ARGC] = {0}, port, num;
+ PinName pin = NC;
+ u32 tConfigDebugInfo = ConfigDebugInfo;
+
+ AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "[ATSG]: _AT_SYSTEM_GPIO_TEST_");
+ if(!arg) {
+ AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "[ATSG] Usage: ATSG=PINNAME(ex:A0)");
+ return;
+ } else {
+ argc = parse_param(arg, argv);
+ if(argc != 2) {
+ AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "[ATSG] Usage: ATSG=PINNAME(ex:A0)");
+ return;
+ }
+ }
+ port = argv[1][0];
+ num = argv[1][1];
+ if(port >= 'a' && port <= 'z')
+ port -= ('a' - 'A');
+ if(num >= 'a' && num <= 'z')
+ num -= ('a' - 'A');
+ switch(port) {
+ case 'A':
+ switch(num) {
+ case '0': pin = PA_0; break; case '1': pin = PA_1; break; case '2': pin = PA_2; break; case '3': pin = PA_3; break;
+ case '4': pin = PA_4; break; case '5': pin = PA_5; break; case '6': pin = PA_6; break; case '7': pin = PA_7; break;
+ }
+ break;
+ case 'B':
+ switch(num) {
+ case '0': pin = PB_0; break; case '1': pin = PB_1; break; case '2': pin = PB_2; break; case '3': pin = PB_3; break;
+ case '4': pin = PB_4; break; case '5': pin = PB_5; break; case '6': pin = PB_6; break; case '7': pin = PB_7; break;
+ }
+ break;
+ case 'C':
+ switch(num) {
+ case '0': pin = PC_0; break; case '1': pin = PC_1; break; case '2': pin = PC_2; break; case '3': pin = PC_3; break;
+ case '4': pin = PC_4; break; case '5': pin = PC_5; break; case '6': pin = PC_6; break; case '7': pin = PC_7; break;
+ case '8': pin = PC_8; break; case '9': pin = PC_9; break;
+ }
+ break;
+ case 'D':
+ switch(num) {
+ case '0': pin = PD_0; break; case '1': pin = PD_1; break; case '2': pin = PD_2; break; case '3': pin = PD_3; break;
+ case '4': pin = PD_4; break; case '5': pin = PD_5; break; case '6': pin = PD_6; break; case '7': pin = PD_7; break;
+ case '8': pin = PD_8; break; case '9': pin = PD_9; break;
+ }
+ break;
+ case 'E':
+ switch(num) {
+ case '0': pin = PE_0; break; case '1': pin = PE_1; break; case '2': pin = PE_2; break; case '3': pin = PE_3; break;
+ case '4': pin = PE_4; break; case '5': pin = PE_5; break; case '6': pin = PE_6; break; case '7': pin = PE_7; break;
+ case '8': pin = PE_8; break; case '9': pin = PE_9; break; case 'A': pin = PE_A; break;
+ }
+ break;
+ case 'F':
+ switch(num) {
+ case '0': pin = PF_0; break; case '1': pin = PF_1; break; case '2': pin = PF_2; break; case '3': pin = PF_3; break;
+ case '4': pin = PF_4; break; case '5': pin = PF_5; break;
+ }
+ break;
+ case 'G':
+ switch(num) {
+ case '0': pin = PG_0; break; case '1': pin = PG_1; break; case '2': pin = PG_2; break; case '3': pin = PG_3; break;
+ case '4': pin = PG_4; break; case '5': pin = PG_5; break; case '6': pin = PG_6; break; case '7': pin = PG_7; break;
+ }
+ break;
+ case 'H':
+ switch(num) {
+ case '0': pin = PH_0; break; case '1': pin = PH_1; break; case '2': pin = PH_2; break; case '3': pin = PH_3; break;
+ case '4': pin = PH_4; break; case '5': pin = PH_5; break; case '6': pin = PH_6; break; case '7': pin = PH_7; break;
+ }
+ break;
+ case 'I':
+ switch(num) {
+ case '0': pin = PI_0; break; case '1': pin = PI_1; break; case '2': pin = PI_2; break; case '3': pin = PI_3; break;
+ case '4': pin = PI_4; break; case '5': pin = PI_5; break; case '6': pin = PI_6; break; case '7': pin = PI_7; break;
+ }
+ break;
+ case 'J':
+ switch(num) {
+ case '0': pin = PJ_0; break; case '1': pin = PJ_1; break; case '2': pin = PJ_2; break; case '3': pin = PJ_3; break;
+ case '4': pin = PJ_4; break; case '5': pin = PJ_5; break; case '6': pin = PJ_6; break;
+ }
+ break;
+ case 'K':
+ switch(num) {
+ case '0': pin = PK_0; break; case '1': pin = PK_1; break; case '2': pin = PK_2; break; case '3': pin = PK_3; break;
+ case '4': pin = PK_4; break; case '5': pin = PK_5; break; case '6': pin = PK_6; break;
+ }
+ break;
+ }
+ if(pin == NC) {
+ AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "[ATSG]: Invalid Pin Name");
+ return;
+ }
+ // Remove debug info massage
+ ConfigDebugInfo = 0;
+ // Initial input control pin
+ gpio_init(&gpio_test, pin);
+ gpio_dir(&gpio_test, PIN_INPUT);// Direction: Input
+ gpio_mode(&gpio_test, PullUp);// Pull-High
+ val = gpio_read(&gpio_test);
+ // Recover debug info massage
+ ConfigDebugInfo = tConfigDebugInfo;
+ AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "[ATSG] %c%c = %d", port, num, val);
+}
+
+void fATSP(void *arg)
+{
+ int argc = 0;
+ char *argv[MAX_ARGC] = {0};
+
+ unsigned long timeout; // ms
+ unsigned long time_begin, time_current;
+
+ gpio_t gpiob_1;
+ int val_old, val_new;
+
+ int expected_zerocount, zerocount;
+ int test_result;
+
+ // parameter check
+ AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "[ATSP]: _AT_SYSTEM_POWER_PIN_TEST_");
+ if(!arg) {
+ AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "[ATSP]: Usage: ATSP=gpiob1[timeout,zerocount]");
+ } else {
+ argc = parse_param(arg, argv);
+ if (argc < 2) {
+ AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "[ATSP]: Usage: ATSP=gpiob1[timeout,zerocount]");
+ return;
+ }
+ }
+
+ if ( strcmp(argv[1], "gpiob1" ) == 0 ) {
+ if (argc < 4) {
+ AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "[ATSP]: Usage: ATSP=gpiob1[timeout,zerocount]");
+ return;
+ }
+
+ // init gpiob1 test
+ test_result = 0;
+ timeout = strtoul(argv[2], NULL, 10);
+ expected_zerocount = atoi(argv[3]);
+ zerocount = 0;
+ val_old = 1;
+
+ sys_log_uart_off();
+
+ gpio_init(&gpiob_1, PB_1);
+ gpio_dir(&gpiob_1, PIN_INPUT);
+ gpio_mode(&gpiob_1, PullDown);
+
+ // gpiob1 test ++
+ time_begin = time_current = xTaskGetTickCount();
+ while (time_current < time_begin + timeout) {
+ val_new = gpio_read(&gpiob_1);
+
+ if (val_new != val_old && val_new == 0) {
+
+ zerocount ++;
+ if (zerocount == expected_zerocount) {
+ test_result = 1;
+ break;
+ }
+ }
+
+ val_old = val_new;
+ time_current = xTaskGetTickCount();
+ }
+ // gpio test --
+
+ sys_log_uart_on();
+
+ if (test_result == 1) {
+ AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "[ATSP]: success");
+ } else {
+ AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "[ATSP]: fail, it only got %d zeros", zerocount);
+ }
+ }
+}
+
+int write_otu_to_system_data(flash_t *flash, uint32_t otu_addr)
+{
+ uint32_t data, i = 0;
+ flash_read_word(flash, FLASH_SYSTEM_DATA_ADDR+0xc, &data);
+ //printf("\n\r[%s] data 0x%x otu_addr 0x%x", __FUNCTION__, data, otu_addr);
+ AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSB]: data 0x%x otu_addr 0x%x", data, otu_addr);
+ if(data == ~0x0) {
+ flash_write_word(flash, FLASH_SYSTEM_DATA_ADDR+0xc, otu_addr);
+ } else {
+ //erase backup sector
+ flash_erase_sector(flash, FLASH_RESERVED_DATA_BASE);
+ //backup system data to backup sector
+ for(i = 0; i < 0x1000; i+= 4) {
+ flash_read_word(flash, FLASH_SYSTEM_DATA_ADDR + i, &data);
+ if(i == 0xc)
+ data = otu_addr;
+ flash_write_word(flash, FLASH_RESERVED_DATA_BASE + i,data);
+ }
+ //erase system data
+ flash_erase_sector(flash, FLASH_SYSTEM_DATA_ADDR);
+ //write data back to system data
+ for(i = 0; i < 0x1000; i+= 4) {
+ flash_read_word(flash, FLASH_RESERVED_DATA_BASE + i, &data);
+ flash_write_word(flash, FLASH_SYSTEM_DATA_ADDR + i,data);
+ }
+ //erase backup sector
+ flash_erase_sector(flash, FLASH_RESERVED_DATA_BASE);
+ }
+ return 0;
+}
+
+void fATSB(void *arg)
+{
+ int argc = 0;
+ char *argv[MAX_ARGC] = {0};
+ u32 boot_gpio, rb_boot_gpio;
+ u8 gpio_pin;
+ u8 uart_port, uart_index;
+ u8 gpio_pin_bar;
+ u8 uart_port_bar;
+ flash_t flash;
+
+ // parameter check
+ AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSB]: _AT_SYSTEM_BOOT_OTU_PIN_SET_");
+ if(!arg) {
+ AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSB]: Usage: ATSB=[GPIO_PIN, TRIGER_MODE, UART]");
+ AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSB]: GPIO_PIN: PB_1, PC_4 ....");
+ AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSB]: TRIGER_MODE: low_trigger, high_trigger");
+ AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSB]: UART: UART0, UART2");
+ AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSB]: example: ATSB=[PC_2, low_trigger, UART2]");
+
+ } else {
+ argc = parse_param(arg, argv);
+ if (argc != 4 ) {
+ AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSB]: Usage: ATSB=[GPIO_PIN, TRIGER_MODE, UART]");
+ AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSB]: GPIO_PIN: PB_1, PC_4 ....");
+ AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSB]: TRIGER_MODE: low_trigger, high_trigger");
+ AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSB]: UART: UART0, UART2");
+ AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSB]: example: ATSB=[PC_2, low_trigger, UART2]");
+ return;
+ }
+ }
+
+ if ( strncmp(argv[1], "P", 1) == 0 && strlen(argv[1]) == 4
+ && (strcmp(argv[2], "low_trigger") == 0 || strcmp(argv[2], "high_trigger") == 0)
+ && strncmp(argv[3], "UART", 4) == 0 && strlen(argv[3]) == 5) {
+ if((0x41 <= argv[1][1] <= 0x45) && (0x30 <= argv[1][3] <= 0x39) &&(0x30 <= argv[1][4] <= 0x32)) {
+ if(strcmp(argv[2], "high_trigger") == 0)
+ gpio_pin = 1<< 7 | ((argv[1][1]-0x41)<<4) | (argv[1][3] - 0x30);
+ else
+ gpio_pin = ((argv[1][1]-0x41)<<4) | (argv[1][3] - 0x30);
+ gpio_pin_bar = ~gpio_pin;
+ uart_index = argv[3][4] - 0x30;
+ if(uart_index == 0)
+ uart_port = (uart_index<<4)|2;
+ else if(uart_index == 2)
+ uart_port = (uart_index<<4)|0;
+ else {
+ AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSB]: Input UART index error. Please choose UART0 or UART2.");
+ AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSB]: example: ATSB=[PC_2, low_trigger, UART2]");
+ return;
+ }
+ uart_port_bar = ~uart_port;
+ boot_gpio = uart_port_bar<<24 | uart_port<<16 | gpio_pin_bar<<8 | gpio_pin;
+ AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSB]:gpio_pin 0x%x", gpio_pin);
+ AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSB]:gpio_pin_bar 0x%x", gpio_pin_bar);
+ AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSB]:uart_port 0x%x", uart_port);
+ AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSB]:uart_port_bar 0x%x", uart_port_bar);
+ AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSB]:boot_gpio 0x%x", boot_gpio);
+ write_otu_to_system_data(&flash, boot_gpio);
+ flash_read_word(&flash, FLASH_SYSTEM_DATA_ADDR+0x0c, &rb_boot_gpio);
+ AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSB]:Read 0x900c 0x%x", rb_boot_gpio);
+ } else {
+ AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSB]: Usage: ATSB=[GPIO_PIN, TRIGER_MODE, UART]");
+ AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSB]: GPIO_PIN: PB_1, PC_4 ....");
+ AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSB]: TRIGER_MODE: low_trigger, high_trigger");
+ AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSB]: UART: UART0, UART2");
+ AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSB]: example: ATSB=[PC_2, low_trigger, UART2]");
+ }
+ } else {
+ AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSB]: Usage: ATSB=[GPIO_PIN, TRIGER_MODE, UART]");
+ AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSB]: GPIO_PIN: PB_1, PC_4 ....");
+ AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSB]: TRIGER_MODE: low_trigger, high_trigger");
+ AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSB]: UART: UART0, UART2");
+ AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSB]: example: ATSB=[PC_2, low_trigger, UART2]");
+ return;
+ }
+}
+#endif
+
+#if (configGENERATE_RUN_TIME_STATS == 1)
+void fATSS(void *arg) // Show CPU stats
+{
+ AT_PRINTK("[ATSS]: _AT_SYSTEM_CPU_STATS_");
+ char *cBuffer = pvPortMalloc(512);
+ if(cBuffer != NULL) {
+ vTaskGetRunTimeStats((char *)cBuffer);
+ AT_PRINTK("%s", cBuffer);
+ }
+ vPortFree(cBuffer);
+}
+#endif
+
+void fATSs(void *arg)
+{
+ int argc = 0;
+ char *argv[MAX_ARGC] = {0};
+
+ AT_PRINTK("[ATS@]: _AT_SYSTEM_DBG_SETTING_");
+ if(!arg) {
+ AT_PRINTK("[ATS@] Usage: ATS@=[LEVLE,FLAG]");
+ } else {
+ argc = parse_param(arg, argv);
+ if(argc == 3) {
+ char *ptmp;
+ gDbgLevel = atoi(argv[1]);
+ gDbgFlag = strtoul(argv[2], &ptmp, 16);
+ }
+ }
+ AT_PRINTK("[ATS@] level = %d, flag = 0x%08X", gDbgLevel, gDbgFlag);
+}
+
+void fATSc(void *arg)
+{
+ int argc = 0, config = 0;
+ char *argv[MAX_ARGC] = {0};
+
+ AT_PRINTK("[ATS!]: _AT_SYSTEM_CONFIG_SETTING_");
+ if(!arg) {
+ AT_PRINTK("[ATS!] Usage: ATS!=[CONFIG(0,1,2),FLAG]");
+ } else {
+ argc = parse_param(arg, argv);
+ if(argc == 3) {
+ char *ptmp;
+ config = atoi(argv[1]);
+ if(config == 0)
+ ConfigDebugErr = strtoul(argv[2], &ptmp, 16);
+ if(config == 1)
+ ConfigDebugInfo = strtoul(argv[2], &ptmp, 16);
+ if(config == 2)
+ ConfigDebugWarn = strtoul(argv[2], &ptmp, 16);
+ }
+ }
+ AT_PRINTK("[ATS!] ConfigDebugErr = 0x%08X", ConfigDebugErr);
+ AT_PRINTK("[ATS!] ConfigDebugInfo = 0x%08X", ConfigDebugInfo);
+ AT_PRINTK("[ATS!] ConfigDebugWarn = 0x%08X", ConfigDebugWarn);
+}
+
+#define SUPPORT_CP_TEST 0
+#if SUPPORT_CP_TEST
+extern void MFi_auth_test(void);
+void fATSM(void *arg)
+{
+ AT_PRINTK("[ATSM]: _AT_SYSTEM_CP_");
+ MFi_auth_test();
+}
+#endif
+
+void fATSt(void *arg)
+{
+ AT_PRINTK("[ATS#]: _AT_SYSTEM_TEST_");
+ DBG_8195A("\nCLK CPU\t\t%d Hz\nRAM heap\t%d bytes\nTCM heap\t%d bytes\n",
+ HalGetCpuClk(), xPortGetFreeHeapSize(), tcm_heap_freeSpace());
+ dump_mem_block_list();
+ tcm_heap_dump();
+ DBG_8195A("\n");
+}
+
+void fATSJ(void *arg)
+{
+ int argc = 0, config = 0;
+ char *argv[MAX_ARGC] = {0};
+ AT_PRINTK("[ATSJ]: _AT_SYSTEM_JTAG_");
+ if(!arg) {
+ AT_PRINTK("[ATS!] Usage: ATSJ=off");
+ } else {
+ argc = parse_param(arg, argv);
+ if (strcmp(argv[1], "off" ) == 0)
+ sys_jtag_off();
+ else
+ AT_PRINTK("ATSL=%s is not supported!", argv[1]);
+ }
+}
+
+void fATSx(void *arg)
+{
+// uint32_t ability = 0;
+ char buf[64];
+
+ AT_PRINTK("[ATS?]: _AT_SYSTEM_HELP_");
+ AT_PRINTK("[ATS?]: COMPILE TIME: %s", RTL8195AFW_COMPILE_TIME);
+// wifi_get_drv_ability(&ability);
+ strcpy(buf, "v");
+// if(ability & 0x1)
+// strcat(buf, "m");
+ strcat(buf, ".3.5." RTL8195AFW_COMPILE_DATE);
+ AT_PRINTK("[ATS?]: SW VERSION: %s", buf);
+}
+#elif ATCMD_VER == ATVER_2
+
+#define ATCMD_VERSION "v2" //ATCMD MAJOR VERSION, AT FORMAT CHANGED
+#define ATCMD_SUBVERSION "2" //ATCMD MINOR VERSION, NEW COMMAND ADDED
+#define ATCMD_REVISION "2" //ATCMD FIX BUG REVISION
+#define SDK_VERSION "v3.5" //SDK VERSION
+extern void sys_reset(void);
+void print_system_at(void *arg);
+extern void print_wifi_at(void *arg);
+extern void print_tcpip_at(void *arg);
+
+// uart version 2 echo info
+extern unsigned char gAT_Echo;
+
+void fATS0(void *arg) {
+ at_printf("\r\n[AT] OK");
+}
+
+void fATSh(void *arg) {
+ // print common AT command
+ at_printf("\r\n[ATS?] ");
+ at_printf("\r\nCommon AT Command:");
+ print_system_at(arg);
+#if CONFIG_WLAN
+ at_printf("\r\nWi-Fi AT Command:");
+ print_wifi_at(arg);
+#endif
+
+#if CONFIG_TRANSPORT
+ at_printf("\r\nTCP/IP AT Command:");
+ print_tcpip_at(arg);
+#endif
+
+ at_printf("\r\n[ATS?] OK");
+}
+
+void fATSR(void *arg) {
+ at_printf("\r\n[ATSR] OK");
+ sys_reset();
+}
+
+void fATSV(void *arg) {
+ char at_buf[32];
+ char fw_buf[32];
+ char cspimode[4] = { 'S', 'D', 'Q', '?' };
+
+ if (fspic_isinit == 0) {
+ flash_turnon();
+ flash_init(&flashobj);
+ SpicDisableRtl8195A();
+ }
+ printf(
+ "DeviceID: %02X, Flash Size: %d bytes, FlashID: %02X%02X%02X/%d, SpicMode: %cIO\n",
+ HalGetChipId(), (u32) (1 << flashobj.SpicInitPara.id[2]),
+ flashobj.SpicInitPara.id[0], flashobj.SpicInitPara.id[1],
+ flashobj.SpicInitPara.id[2], flashobj.SpicInitPara.flashtype,
+ cspimode[flashobj.SpicInitPara.Mode.BitMode]);
+ // get at version
+ strcpy(at_buf, ATCMD_VERSION"."ATCMD_SUBVERSION"."ATCMD_REVISION);
+
+ // get fw version
+ strcpy(fw_buf, SDK_VERSION);
+ printf("%s,%s(%s)\n", at_buf, fw_buf, RTL8195AFW_COMPILE_TIME);
+ at_printf("\r\n[ATSV] OK:%s,%s(%s)", at_buf, fw_buf,
+ RTL8195AFW_COMPILE_TIME);
+}
+
+#if defined(configUSE_WAKELOCK_PMU) && (configUSE_WAKELOCK_PMU == 1)
+
+void fATSP(void *arg) {
+ int argc = 0;
+ char *argv[MAX_ARGC] = { 0 };
+
+ uint32_t lock_id;
+ uint32_t bitmap;
+
+ if (!arg) {
+ AT_DBG_MSG(AT_FLAG_COMMON, AT_DBG_ERROR,
+ "\r\n[ATSP] Usage: ATSP=");
+ at_printf("\r\n[ATSP] ERROR:1");
+ return;
+ } else {
+ if ((argc = parse_param(arg, argv)) != 2) {
+ AT_DBG_MSG(AT_FLAG_COMMON, AT_DBG_ERROR,
+ "\r\n[ATSP] Usage: ATSP=");
+ at_printf("\r\n[ATSP] ERROR:1");
+ return;
+ }
+ }
+
+ switch (argv[1][0]) {
+ case 'a': // acquire
+ {
+ acquire_wakelock(WAKELOCK_OS);
+ //at_printf("\r\n[ATSP] wakelock:0x%08x", get_wakelock_status());
+ break;
+ }
+
+ case 'r': // release
+ {
+ release_wakelock(WAKELOCK_OS);
+ //at_printf("\r\n[ATSP] wakelock:0x%08x", get_wakelock_status());
+ break;
+ }
+
+ case '?': // get status
+ break;
+ default:
+ AT_DBG_MSG(AT_FLAG_COMMON, AT_DBG_ERROR,
+ "\r\n[ATSP] Usage: ATSP=");
+ at_printf("\r\n[ATSP] ERROR:2");
+ return;
+ }
+ bitmap = pmu_get_wakelock_status();
+ at_printf("\r\n[ATSP] OK:%s", (bitmap&WAKELOCK_OS)?"1":"0");
+}
+#endif
+
+void fATSE(void *arg) {
+ int argc = 0;
+ int echo = 0, mask = gDbgFlag, dbg_lv = gDbgLevel;
+ char *argv[MAX_ARGC] = { 0 };
+ int err_no = 0;
+
+ AT_DBG_MSG(AT_FLAG_COMMON, AT_DBG_ALWAYS,
+ "[ATSE]: _AT_SYSTEM_ECHO_DBG_SETTING");
+ if (!arg) {
+ AT_DBG_MSG(AT_FLAG_COMMON, AT_DBG_ERROR,
+ "[ATSE] Usage: ATSE=,,");
+ err_no = 1;
+ goto exit;
+ }
+
+ argc = parse_param(arg, argv);
+
+ if (argc < 2 || argc > 4) {
+ err_no = 2;
+ goto exit;
+ }
+
+#if CONFIG_EXAMPLE_UART_ATCMD
+ if (argv[1] != NULL) {
+ echo = atoi(argv[1]);
+ if (echo > 1 || echo < 0) {
+ err_no = 3;
+ goto exit;
+ }
+ gAT_Echo = echo ? 1 : 0;
+ }
+#endif
+
+ if ((argc > 2) && (argv[2] != NULL)) {
+ mask = strtoul(argv[2], NULL, 0);
+ at_set_debug_mask(mask);
+ }
+
+ if ((argc == 4) && (argv[3] != NULL)) {
+ dbg_lv = strtoul(argv[3], NULL, 0);
+ at_set_debug_level(dbg_lv);
+ }
+
+ exit: if (err_no)
+ at_printf("\r\n[ATSE] ERROR:%d", err_no);
+ else
+ at_printf("\r\n[ATSE] OK");
+ return;
+}
+#if CONFIG_WLAN
+#if CONFIG_WEBSERVER
+#include "wifi_structures.h"
+#include "wifi_constants.h"
+extern rtw_wifi_setting_t wifi_setting;
+void fATSW(void *arg) {
+ int argc = 0;
+ char *argv[MAX_ARGC] = {0};
+
+ if (!arg) {
+ AT_DBG_MSG(AT_FLAG_COMMON, AT_DBG_ERROR, "\r\n[ATSW] Usage: ATSW=");
+ at_printf("\r\n[ATSW] ERROR:1");
+ return;
+ } else {
+ if((argc = parse_param(arg, argv)) != 2) {
+ AT_DBG_MSG(AT_FLAG_COMMON, AT_DBG_ERROR, "\r\n[ATSW] Usage: ATSW=");
+ at_printf("\r\n[ATSW] ERROR:1");
+ return;
+ }
+ }
+
+ if(argv[1][0]!='c'&&argv[1][0]!='s') {
+ AT_DBG_MSG(AT_FLAG_COMMON, AT_DBG_ERROR, "\r\n[ATSW] Usage: ATSW=");
+ at_printf("\r\n[ATSW] ERROR:2");
+ return;
+ }
+
+ // make sure AP mode
+ LoadWifiConfig();
+ if(wifi_setting.mode != RTW_MODE_AP) {
+ at_printf("\r\n[ATSW] ERROR:3");
+ return;
+ }
+
+ switch(argv[1][0]) {
+ case 'c': // create webserver
+ {
+ start_web_server();
+ break;
+ }
+ case 's': // stop webserver
+ {
+ stop_web_server();
+ break;
+ }
+ }
+ at_printf("\r\n[ATSW] OK");
+}
+#endif
+
+extern int EraseApinfo();
+//extern int Erase_Fastconnect_data();
+
+void fATSY(void *arg) {
+#if CONFIG_EXAMPLE_WLAN_FAST_CONNECT
+// Erase_Fastconnect_data();
+#endif
+
+#if CONFIG_WEBSERVER
+ EraseApinfo();
+#endif
+
+#if CONFIG_EXAMPLE_UART_ATCMD
+ extern int reset_uart_atcmd_setting(void);
+ reset_uart_atcmd_setting();
+#endif
+
+#if CONFIG_OTA_UPDATE
+ // Reset ota image signature
+ cmd_ota_image(0);
+#endif
+
+ at_printf("\r\n[ATSY] OK");
+ // reboot
+ sys_reset();
+}
+
+#if CONFIG_OTA_UPDATE
+extern int wifi_is_connected_to_ap(void);
+void fATSO(void *arg) {
+ int argc = 0;
+ char *argv[MAX_ARGC] = { 0 };
+
+ if (!arg) {
+ AT_DBG_MSG(AT_FLAG_OTA, AT_DBG_ERROR,
+ "\r\n[ATSO] Usage: ATSO=,");
+ at_printf("\r\n[ATSO] ERROR:1");
+ return;
+ }
+ argv[0] = "update";
+ if ((argc = parse_param(arg, argv)) != 3) {
+ AT_DBG_MSG(AT_FLAG_OTA, AT_DBG_ERROR,
+ "\r\n[ATSO] Usage: ATSO=,");
+ at_printf("\r\n[ATSO] ERROR:1");
+ return;
+ }
+
+ // check wifi connect first
+ if (wifi_is_connected_to_ap() == 0) {
+ cmd_update(argc, argv);
+ at_printf("\r\n[ATSO] OK");
+
+ } else {
+ at_printf("\r\n[ATSO] ERROR:3");
+ }
+}
+
+void fATSC(void *arg) {
+ int argc = 0;
+ char *argv[MAX_ARGC] = { 0 };
+ int cmd = 0;
+
+ if (!arg) {
+ AT_DBG_MSG(AT_FLAG_OTA, AT_DBG_ERROR, "\r\n[ATSC] Usage: ATSC=<0/1>");
+ at_printf("\r\n[ATSC] ERROR:1");
+ return;
+ }
+ if ((argc = parse_param(arg, argv)) != 2) {
+ AT_DBG_MSG(AT_FLAG_OTA, AT_DBG_ERROR, "\r\n[ATSC] Usage: ATSC=<0/1>");
+ at_printf("\r\n[ATSC] ERROR:1");
+ return;
+ }
+
+ cmd = atoi(argv[1]);
+
+ if ((cmd != 0) && (cmd != 1)) {
+ at_printf("\r\n[ATSC] ERROR:2");
+ return;
+ }
+
+ at_printf("\r\n[ATSC] OK");
+
+ if (cmd == 1) {
+ cmd_ota_image(1);
+ } else {
+ cmd_ota_image(0);
+ }
+ // reboot
+ sys_reset();
+}
+#endif
+
+#if CONFIG_EXAMPLE_UART_ATCMD
+extern const u32 log_uart_support_rate[];
+
+void fATSU(void *arg) {
+ int argc = 0;
+ char *argv[MAX_ARGC] = { 0 };
+ u32 baud = 0;
+ u8 databits = 0;
+ u8 stopbits = 0;
+ u8 parity = 0;
+ u8 flowcontrol = 0;
+ u8 configmode = 0;
+ int i;
+ UART_LOG_CONF uartconf;
+
+ if (!arg) {
+ AT_DBG_MSG(AT_FLAG_COMMON, AT_DBG_ERROR,
+ "[ATSU] Usage: ATSU=,,,,,");
+ at_printf("\r\n[ATSU] ERROR:1");
+ return;
+ }
+ if ((argc = parse_param(arg, argv)) != 7) {
+ if(argv[1][0] == '?') {
+ read_uart_atcmd_setting_from_system_data(&uartconf);
+ at_printf("\r\n");
+ at_printf( "AT_UART_CONF: %d,%d,%d,%d,%d",
+ uartconf.BaudRate, uartconf.DataBits, uartconf.StopBits,
+ uartconf.Parity, uartconf.FlowControl);
+// return;
+ }
+ else {
+ AT_DBG_MSG(AT_FLAG_COMMON, AT_DBG_ERROR,
+ "[ATSU] Usage: ATSU=,,,,,");
+ at_printf("\r\n[ATSU] ERROR:1");
+ return;
+ }
+ }
+ else {
+ baud = atoi(argv[1]);
+ databits = atoi(argv[2]);
+ stopbits = atoi(argv[3]);
+ parity = atoi(argv[4]);
+ flowcontrol = atoi(argv[5]);
+ configmode = atoi(argv[6]);
+ /*
+ // Check Baud rate
+ for (i=0; log_uart_support_rate[i]!=0xFFFFFF; i++) {
+ if (log_uart_support_rate[i] == baud) {
+ break;
+ }
+ }
+
+ if (log_uart_support_rate[i]== 0xFFFFFF) {
+ at_printf("\r\n[ATSU] ERROR:2");
+ return;
+ }
+ */
+ if (((databits < 5) || (databits > 8)) || ((stopbits < 1) || (stopbits > 2))
+ || ((parity < 0) || (parity > 2))
+ || ((flowcontrol < 0) || (flowcontrol > 1))
+ || ((configmode < 0) || (configmode > 3)) ) {
+ at_printf("\r\n[ATSU] ERROR:2");
+ return;
+ }
+ memset((void*) &uartconf, 0, sizeof(UART_LOG_CONF));
+ uartconf.BaudRate = baud;
+ uartconf.DataBits = databits;
+ uartconf.StopBits = stopbits;
+ uartconf.Parity = parity;
+ uartconf.FlowControl = flowcontrol;
+ AT_DBG_MSG(AT_FLAG_COMMON, AT_DBG_ALWAYS, "AT_UART_CONF: %d,%d,%d,%d,%d",
+ uartconf.BaudRate, uartconf.DataBits, uartconf.StopBits,
+ uartconf.Parity, uartconf.FlowControl);
+ switch (configmode) {
+ case 0: // set current configuration, won't save
+ uart_atcmd_reinit(&uartconf);
+ break;
+ case 1: // set current configuration, and save
+ write_uart_atcmd_setting_to_system_data(&uartconf);
+ uart_atcmd_reinit(&uartconf);
+ break;
+ case 2: // set configuration, reboot to take effect
+ write_uart_atcmd_setting_to_system_data(&uartconf);
+ break;
+ }
+ }
+ at_printf("\r\n[ATSU] OK");
+}
+#endif //#if CONFIG_EXAMPLE_UART_ATCMD
+#endif //#if CONFIG_WLAN
+
+void fATSG(void *arg) {
+ gpio_t gpio_ctrl;
+ int argc = 0, val, error_no = 0;
+ char *argv[MAX_ARGC] = { 0 }, port, num;
+ PinName pin = NC;
+
+ AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "[ATSG]: _AT_SYSTEM_GPIO_CTRL_");
+
+ if (!arg) {
+ AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ERROR,
+ "[ATSG] Usage: ATSG=,,,,");
+ error_no = 1;
+ goto exit;
+ }
+ if ((argc = parse_param(arg, argv)) < 3) {
+ AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ERROR,
+ "[ATSG] Usage: ATSG=,,,,");
+ error_no = 2;
+ goto exit;
+ }
+
+ port = argv[2][1];
+ num = strtoul(&argv[2][3], NULL, 0);
+ port -= 'A';
+ pin = (port << 4 | num);
+ AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "PORT: %s[%d]", argv[2], pin);
+
+ if (gpio_set(pin) == 0xff) {
+ AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ERROR, "[ATSG]: Invalid Pin Name [%d]",
+ pin);
+ error_no = 3;
+ goto exit;
+ }
+
+ gpio_init(&gpio_ctrl, pin);
+ if (argv[4]) {
+ int dir = atoi(argv[4]);
+ AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "DIR: %s", argv[4]);
+ gpio_dir(&gpio_ctrl, dir);
+ }
+ if (argv[5]) {
+ int pull = atoi(argv[5]);
+ AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "PULL: %s", argv[5]);
+ gpio_mode(&gpio_ctrl, pull);
+ }
+ if (argv[1][0] == 'R') {
+ val = gpio_read(&gpio_ctrl);
+ } else {
+ val = atoi(argv[3]);
+ gpio_write(&gpio_ctrl, val);
+ }
+
+ exit: if (error_no) {
+ at_printf("\r\n[ATSG] ERROR:%d", error_no);
+ } else {
+ at_printf("\r\n[ATSG] OK:%d", val);
+ }
+}
+
+#endif //#elif ATCMD_VER == ATVER_2
+#if defined(configUSE_WAKELOCK_PMU) && (configUSE_WAKELOCK_PMU == 1)
+/*
+ * bitmask:
+ * bit0: OS
+ * bit1: WLAN
+ * bit2: LOGUART
+ * bit3: SDIO
+ */
+void fATSL(void *arg) {
+ int argc = 0;
+ char *argv[MAX_ARGC] = { 0 };
+ int err_no = 0;
+ uint32_t lock_id;
+
+ AT_DBG_MSG(AT_FLAG_OS, AT_DBG_ALWAYS, "[ATSL]: _AT_SYS_WAKELOCK_TEST_");
+
+ if (!arg) {
+ AT_DBG_MSG(AT_FLAG_OS, AT_DBG_ALWAYS,
+ "[ATSL] Usage ATSL=[a/r/?][bitmask]");
+ err_no = 1;
+ goto exit;
+ } else {
+ argc = parse_param(arg, argv);
+ if (argc < 2) {
+ AT_DBG_MSG(AT_FLAG_OS, AT_DBG_ALWAYS,
+ "[ATSL] Usage ATSL=[a/r/?][bitmask]");
+ err_no = 2;
+ goto exit;
+ }
+ }
+
+ switch (argv[1][0]) {
+ case 'a': // acquire
+ {
+ if (argc == 3) {
+ lock_id = strtoul(argv[2], NULL, 16);
+ acquire_wakelock(lock_id);
+ }
+ AT_DBG_MSG(AT_FLAG_OS, AT_DBG_ALWAYS, "[ATSL] wakelock:0x%08x",
+ pmu_get_wakelock_status());
+ break;
+ }
+
+ case 'r': // release
+ {
+ if (argc == 3) {
+ lock_id = strtoul(argv[2], NULL, 16);
+ release_wakelock(lock_id);
+ }
+ AT_DBG_MSG(AT_FLAG_OS, AT_DBG_ALWAYS, "[ATSL] wakelock:0x%08x",
+ pmu_get_wakelock_status());
+ break;
+ }
+
+ case '?': // get status
+ AT_DBG_MSG(AT_FLAG_OS, AT_DBG_ALWAYS, "[ATSL] wakelock:0x%08x",
+ pmu_get_wakelock_status());
+#if (configGENERATE_RUN_TIME_STATS == 1)
+ char *cBuffer = pvPortMalloc(512);
+ if (cBuffer != NULL) {
+ pmu_get_wakelock_hold_stats((char *) cBuffer);
+ AT_DBG_MSG(AT_FLAG_OS, AT_DBG_ALWAYS, "%s", cBuffer);
+ }
+ vPortFree(cBuffer);
+#endif
+ break;
+
+#if (configGENERATE_RUN_TIME_STATS == 1)
+ case 'c': // clean wakelock info (for recalculate wakelock hold time)
+ AT_DBG_MSG(AT_FLAG_OS, AT_DBG_ALWAYS, "[ATSL] clean wakelock stat");
+ pmu_clean_wakelock_stat();
+ break;
+#endif
+ default:
+ AT_DBG_MSG(AT_FLAG_OS, AT_DBG_ALWAYS,
+ "[ATSL] Usage ATSL=[a/r/?][bitmask]");
+ err_no = 3;
+ break;
+ }
+ exit:
+#if ATCMD_VER == ATVER_2
+ if (err_no)
+ at_printf("\r\n[ATSL] ERROR:%d", err_no);
+ else
+ at_printf("\r\n[ATSL] OK:0x%08x", pmu_get_wakelock_status());
+#endif
+ return;
+}
+
+#if CONFIG_UART_XMODEM
+void fATSX(void *arg)
+{
+ if (HalGetChipId() < CHIP_ID_8195AM) {
+
+ // use xmodem to update, RX: PC_0, TX: PC_3, baudrate: 1M
+ OTU_FW_Update(0, 0, 115200);
+ // use xmodem to update, RX: PE_3, TX: PE_0, baudrate: 1M
+ // JTAG Off!
+ // OTU_FW_Update(0, 1, 115200);
+ }
+ else {
+ // use xmodem to update, RX: PA_6, TX: PA_7, baudrate: 1M
+ OTU_FW_Update(0, 2, 115200);
+ };
+ at_printf("\r\n[ATSX] OK");
+}
+#endif
+
+#endif
+
+void print_hex_dump(uint8_t *buf, int len, unsigned char k) {
+ uint32_t ss[2];
+ ss[0] = 0x78323025; // "%02x"
+ ss[1] = k; // ","...'\0'
+ uint8_t * ptr = buf;
+ while (len--) {
+ if (len == 0)
+ ss[1] = 0;
+ printf((uint8_t *) &ss[0], *ptr++);
+ }
+}
+
+//ATFD - Flash Data Dump
+void fATFD(void *arg) {
+ int argc = 0;
+ char *argv[MAX_ARGC] = { 0 };
+#if DEBUG_AT_USER_LEVEL > 3
+ printf("ATFD: _AT_FLASH_DUMP_\n");
+#endif
+ if (!arg) {
+ printf("Usage: ATFD=faddr(HEX),[size]\n");
+ } else {
+ argc = parse_param(arg, argv);
+ if (argc >= 1) {
+ int addr;
+ sscanf(argv[1], "%x", &addr);
+ int size = 0;
+ if (argc > 2)
+ size = atoi(argv[2]);
+ if (size <= 0 || size > 16384)
+ size = 1;
+ u32 symbs_line = 32;
+ u32 rdsize = 8 * symbs_line;
+ uint8_t *flash_data = (uint8_t *) malloc(rdsize);
+ while (size) {
+ if (size < rdsize)
+ rdsize = size;
+ else
+ rdsize = 8 * symbs_line;
+ flash_stream_read(&flashobj, addr, rdsize, flash_data);
+ uint8_t *ptr = flash_data;
+ while (ptr < flash_data + rdsize) {
+ if (symbs_line > size)
+ symbs_line = size;
+ printf("%08X ", addr);
+ print_hex_dump(ptr, symbs_line, ' ');
+ printf("\r\n");
+ addr += symbs_line;
+ ptr += symbs_line;
+ size -= symbs_line;
+ if (size == 0)
+ break;
+ }
+ }
+ free(flash_data);
+ }
+ }
+}
+
+void fATFO(void *arg) {
+ int argc = 0;
+ char *argv[MAX_ARGC] = { 0 };
+#if DEBUG_AT_USER_LEVEL > 3
+ printf("ATFO: _AT_FLASH_OTP_DUMP_\n");
+#endif
+ if (!arg) {
+ printf("Usage: ATFO=faddr(HEX),[size]\n");
+ } else {
+ argc = parse_param(arg, argv);
+ if (argc >= 1) {
+ int addr;
+ sscanf(argv[1], "%x", &addr);
+ int size = 0;
+ if (argc > 2)
+ size = atoi(argv[2]);
+ if (size <= 0 || size > 16384)
+ size = 1;
+ u32 symbs_line = 32;
+ u32 rdsize = 8 * symbs_line;
+ uint8_t *flash_data = (uint8_t *) malloc(rdsize);
+ while (size) {
+ if (size < rdsize)
+ rdsize = size;
+ else
+ rdsize = 8 * symbs_line;
+ flash_otp_read(&flashobj, addr, rdsize, flash_data);
+ uint8_t *ptr = flash_data;
+ while (ptr < flash_data + rdsize) {
+ if (symbs_line > size)
+ symbs_line = size;
+ printf("%08X ", addr);
+ print_hex_dump(ptr, symbs_line, ' ');
+ printf("\r\n");
+ addr += symbs_line;
+ ptr += symbs_line;
+ size -= symbs_line;
+ if (size == 0)
+ break;
+ }
+ }
+ free(flash_data);
+ }
+ }
+}
+
+// Mem info
+void fATST(void *arg) {
+ extern void dump_mem_block_list(void); // heap_5.c
+ printf("\nCLK CPU\t\t%d Hz\nRAM heap\t%d bytes\nTCM heap\t%d bytes\n",
+ HalGetCpuClk(), xPortGetFreeHeapSize(), tcm_heap_freeSpace());
+#if CONFIG_DEBUG_LOG > 1
+ dump_mem_block_list();
+ tcm_heap_dump();
+#endif;
+ printf("\n");
+#if (configGENERATE_RUN_TIME_STATS == 1)
+ char *cBuffer = pvPortMalloc(512);
+ if(cBuffer != NULL) {
+ vTaskGetRunTimeStats((char *)cBuffer);
+ printf("%s", cBuffer);
+ }
+ vPortFree(cBuffer);
+#endif
+}
+
+#if 0
+#if 1
+#include "drv_types.h" // or #include "wlan_lib.h"
+#else
+#include "wifi_constants.h"
+#include "wifi_structures.h"
+#include "wlan_lib.h" // or #include "drv_types.h"
+#endif
+#include "hal_com_reg.h"
+// extern Rltk_wlan_t rltk_wlan_info[2];
+void fATXT(void *arg)
+{
+#if DEBUG_AT_USER_LEVEL > 3
+ printf("ATWT: _AT_CFG_DUMP_\n");
+#endif
+ int size = 512;
+ int addr = 0;
+ uint8_t *blk_data = (uint8_t *)malloc(size);
+ memset(blk_data, 0xff, size);
+ if(blk_data) {
+ uint8_t * ptr = blk_data;
+ Hal_ReadEFuse(*(_adapter **)(rltk_wlan_info->priv), 0, 0, 512, ptr, 1);
+ //rtw_flash_map_update(*(_adapter **)(rltk_wlan_info->priv), 512);
+ u32 symbs_line = 32;
+ while(addr < size) {
+ if(symbs_line > size) symbs_line = size;
+ printf("%08X ", addr);
+ print_hex_dump(ptr, symbs_line, ' ');
+ printf("\r\n");
+ addr += symbs_line;
+ ptr += symbs_line;
+ size -= symbs_line;
+ if(size == 0) break;
+ }
+ free(blk_data);
+ }
+}
+#endif
+log_item_t at_sys_items[] = {
+#if (ATCMD_VER == ATVER_1)
+ { "ATSD", fATSD}, // Dump register
+ { "ATSE", fATSE}, // Edit register
+ { "ATSC", fATSC}, // Clear OTA signature
+ { "ATSR", fATSR}, // Recover OTA signature
+#if CONFIG_UART_XMODEM
+ { "ATSY", fATSY}, // uart ymodem upgrade
+#endif
+#if SUPPORT_MP_MODE
+ { "ATSA", fATSA}, // MP ADC test
+ { "ATSG", fATSG}, // MP GPIO test
+ { "ATSP", fATSP}, // MP Power related test
+ { "ATSB", fATSB}, // OTU PIN setup
+#endif
+#if (configGENERATE_RUN_TIME_STATS == 1)
+ { "ATSS", fATSS}, // Show CPU stats
+#endif
+#if SUPPORT_CP_TEST
+ { "ATSM", fATSM}, // Apple CP test
+#endif
+ { "ATSJ", fATSJ}, //trun off JTAG
+ { "ATS@", fATSs}, // Debug message setting
+ { "ATS!", fATSc}, // Debug config setting
+ { "ATS#", fATSt}, // test command
+ { "ATS?", fATSx}, // Help
+#elif ATCMD_VER == ATVER_2 //#if ATCMD_VER == ATVER_1
+ { "AT", fATS0 }, // test AT command ready
+ { "ATS?", fATSh }, // list all AT command
+ { "ATSR", fATSR }, // system restart
+ { "ATSV", fATSV }, // show version info
+ { "ATSP", fATSP }, // power saving mode
+ { "ATSE", fATSE }, // enable and disable echo
+#if CONFIG_WLAN
+#if CONFIG_WEBSERVER
+ { "ATSW", fATSW}, // start webserver
+#endif
+ { "ATSY", fATSY }, // factory reset
+#if CONFIG_OTA_UPDATE
+ { "ATSO", fATSO }, // ota upgrate
+ { "ATSC", fATSC }, // chose the activited image
+#endif
+#if CONFIG_EXAMPLE_UART_ATCMD
+ { "ATSU", fATSU }, // AT uart configuration
+#endif
+#endif
+ { "ATSG", fATSG }, // GPIO control
+#if CONFIG_UART_XMODEM
+ { "ATSX", fATSX}, // uart xmodem upgrade
+#endif
+ { "ATSD", fATSD }, // Dump register
+ { "ATXD", fATXD }, // Write register
+#endif // end of #if ATCMD_VER == ATVER_1
+
+// Following commands exist in two versions
+#if defined(configUSE_WAKELOCK_PMU) && (configUSE_WAKELOCK_PMU == 1)
+ { "ATSL", fATSL }, // wakelock test
+#endif
+ { "ATFD", fATFD }, // Flash Data Damp
+ { "ATFO", fATFO }, // Flash OTP Damp
+ { "ATST", fATST }, // add pvvx: mem info
+// { "ATXT", fATXT }, // add pvvx: cfg_wifi
+ { "ATSI", fATSI } // Dev/Ports Info
+};
+
+#if ATCMD_VER == ATVER_2
+void print_system_at(void *arg) {
+ int index;
+ int cmd_len = 0;
+
+ cmd_len = sizeof(at_sys_items) / sizeof(at_sys_items[0]);
+ for (index = 0; index < cmd_len; index++)
+ at_printf("\r\n%s", at_sys_items[index].log_cmd);
+}
+#endif
+void at_sys_init(void) {
+ log_service_add_table(at_sys_items,
+ sizeof(at_sys_items) / sizeof(at_sys_items[0]));
+}
+
+#if SUPPORT_LOG_SERVICE
+log_module_init(at_sys_init);
+#endif
+
+#endif //#ifdef CONFIG_AT_SYS
diff --git a/RTLGDB/USDK/component/common/api/at_cmd/atcmd_sys.h b/RTLGDB/USDK/component/common/api/at_cmd/atcmd_sys.h
new file mode 100644
index 0000000..9eaee49
--- /dev/null
+++ b/RTLGDB/USDK/component/common/api/at_cmd/atcmd_sys.h
@@ -0,0 +1,6 @@
+#ifndef __ATCMD_SYS_H__
+#define __ATCMD_SYS_H__
+#ifdef CONFIG_AT_SYS
+#endif //
+
+#endif
diff --git a/RTLGDB/USDK/component/common/api/at_cmd/atcmd_wifi.c b/RTLGDB/USDK/component/common/api/at_cmd/atcmd_wifi.c
new file mode 100644
index 0000000..27b564e
--- /dev/null
+++ b/RTLGDB/USDK/component/common/api/at_cmd/atcmd_wifi.c
@@ -0,0 +1,2836 @@
+#include "FreeRTOS.h"
+#include "task.h"
+#include "semphr.h"
+#include "log_service.h"
+#include "atcmd_wifi.h"
+#include
+#include "tcpip.h"
+#include
+#if CONFIG_WLAN
+#include
+#include
+#include
+#endif
+
+#if ATCMD_VER == ATVER_2
+#include "flash_api.h"
+#include "device_lock.h"
+#include
+#endif
+
+#if ATCMD_VER == ATVER_2 || WIFI_LOGO_CERTIFICATION_CONFIG
+#include
+#endif
+
+/******************************************************************************/
+#define _AT_WLAN_SET_SSID_ "ATW0"
+#define _AT_WLAN_SET_PASSPHRASE_ "ATW1"
+#define _AT_WLAN_SET_KEY_ID_ "ATW2"
+#define _AT_WLAN_AP_SET_SSID_ "ATW3"
+#define _AT_WLAN_AP_SET_SEC_KEY_ "ATW4"
+#define _AT_WLAN_AP_SET_CHANNEL_ "ATW5"
+#define _AT_WLAN_SET_BSSID_ "ATW6"
+#define _AT_WLAN_AP_ACTIVATE_ "ATWA"
+#define _AT_WLAN_AP_STA_ACTIVATE_ "ATWB"
+#define _AT_WLAN_JOIN_NET_ "ATWC"
+#define _AT_WLAN_DISC_NET_ "ATWD"
+#define _AT_WLAN_WEB_SERVER_ "ATWE"
+#define _AT_WLAN_P2P_FIND_ "ATWF"
+#define _AT_WLAN_P2P_START_ "ATWG"
+#define _AT_WLAN_P2P_STOP_ "ATWH"
+#define _AT_WLAN_PING_TEST_ "ATWI"
+#define _AT_WLAN_P2P_CONNECT_ "ATWJ"
+#define _AT_WLAN_P2P_DISCONNECT_ "ATWK"
+#define _AT_WLAN_SSL_CLIENT_ "ATWL"
+#define _AT_WLAN_PROMISC_ "ATWM"
+#define _AT_WLAN_P2P_INFO_ "ATWN"
+#define _AT_WLAN_OTA_UPDATE_ "ATWO"
+#define _AT_WLAN_POWER_ "ATWP"
+#define _AT_WLAN_SIMPLE_CONFIG_ "ATWQ"
+#define _AT_WLAN_GET_RSSI_ "ATWR"
+#define _AT_WLAN_SCAN_ "ATWS"
+#define _AT_WLAN_SCAN_WITH_SSID_ "ATWs"
+#define _AT_WLAN_TCP_TEST_ "ATWT"
+#define _AT_WLAN_UDP_TEST_ "ATWU"
+#define _AT_WLAN_WPS_ "ATWW"
+#define _AT_WLAN_AP_WPS_ "ATWw"
+#define _AT_WLAN_AIRKISS_ "ATWX"
+#define _AT_WLAN_IWPRIV_ "ATWZ"
+#define _AT_WLAN_INFO_ "ATW?"
+
+#define _AT_WLAN_EXTEND_POWER_MODE_ "ATXP"
+
+#ifndef CONFIG_SSL_CLIENT
+#define CONFIG_SSL_CLIENT 0
+#endif
+#ifndef CONFIG_WEBSERVER
+#define CONFIG_WEBSERVER 0
+#endif
+#ifndef CONFIG_OTA_UPDATE
+#define CONFIG_OTA_UPDATE 0
+#endif
+#ifndef CONFIG_BSD_TCP
+#define CONFIG_BSD_TCP 1
+#endif
+#ifndef CONFIG_ENABLE_P2P
+#define CONFIG_ENABLE_P2P 0
+#endif
+#define SCAN_WITH_SSID 0
+#if CONFIG_WEBSERVER
+#define CONFIG_READ_FLASH 1
+extern rtw_wifi_setting_t wifi_setting;
+#endif
+
+#ifndef CONFIG_WOWLAN_SERVICE
+#define CONFIG_WOWLAN_SERVICE 0
+#endif
+
+#if CONFIG_LWIP_LAYER
+extern void cmd_tcp(int argc, char **argv);
+extern void cmd_udp(int argc, char **argv);
+extern void cmd_ping(int argc, char **argv);
+extern void cmd_ssl_client(int argc, char **argv);
+#endif
+
+#if CONFIG_WLAN
+extern void cmd_promisc(int argc, char **argv);
+extern void cmd_update(int argc, char **argv);
+extern void cmd_simple_config(int argc, char **argv);
+#if CONFIG_ENABLE_WPS
+extern void cmd_wps(int argc, char **argv);
+#endif
+
+#if defined(CONFIG_ENABLE_WPS_AP) && CONFIG_ENABLE_WPS_AP
+extern void cmd_ap_wps(int argc, char **argv);
+extern int wpas_wps_dev_config(u8 *dev_addr, u8 bregistrar);
+#endif
+#if CONFIG_ENABLE_P2P
+extern void cmd_wifi_p2p_start(int argc, char **argv);
+extern void cmd_wifi_p2p_stop(int argc, char **argv);
+extern void cmd_p2p_listen(int argc, char **argv);
+extern void cmd_p2p_find(int argc, char **argv);
+extern void cmd_p2p_peers(int argc, char **argv);
+extern void cmd_p2p_info(int argc, char **argv);
+extern void cmd_p2p_disconnect(int argc, char **argv);
+extern void cmd_p2p_connect(int argc, char **argv);
+extern int cmd_wifi_p2p_auto_go_start(int argc, char **argv);
+#endif //CONFIG_ENABLE_P2P
+#if CONFIG_AIRKISS
+extern int airkiss_start();
+#endif
+#if CONFIG_LWIP_LAYER
+extern struct netif xnetif[NET_IF_NUM];
+#endif
+#if CONFIG_WOWLAN_SERVICE
+extern void cmd_wowlan_service(int argc, char **argv);
+#endif
+#if CONFIG_INIC_CMD_RSP
+extern void inic_c2h_wifi_info(const char *atcmd, char status);
+extern void inic_c2h_msg(const char *atcmd, u8 status, char *msg, u16 msg_len);
+#endif
+
+/* fastconnect use wifi AT command. Not init_wifi_struct when log service disabled
+ * static initialize all values for using fastconnect when log service disabled
+ */
+static rtw_network_info_t wifi = {
+ {0}, // ssid
+ {0}, // bssid
+ 0, // security
+ NULL, // password
+ 0, // password len
+ -1 // key id
+};
+
+static rtw_ap_info_t ap = {0};
+static unsigned char password[65] = {0};
+
+#if ATCMD_VER == ATVER_2 || WIFI_LOGO_CERTIFICATION_CONFIG
+unsigned char sta_ip[4] = {192,168,1,80}, sta_netmask[4] = {255,255,255,0}, sta_gw[4] = {192,168,1,1};
+#endif
+
+#if ATCMD_VER == ATVER_2
+unsigned char dhcp_mode_sta = 1, dhcp_mode_ap = 1;
+unsigned char ap_ip[4] = {192,168,43,1}, ap_netmask[4] = {255,255,255,0}, ap_gw[4] = {192,168,43,1};
+static void atcmd_wifi_disconn_hdl( char* buf, int buf_len, int flags, void* userdata);
+#endif
+
+extern unsigned char wifi_mode; // = RTW_MODE_NONE;
+
+static void init_wifi_struct(void)
+{
+ memset(wifi.ssid.val, 0, sizeof(wifi.ssid.val));
+ memset(wifi.bssid.octet, 0, ETH_ALEN);
+ memset(password, 0, sizeof(password));
+ wifi.ssid.len = 0;
+ wifi.password = NULL;
+ wifi.password_len = 0;
+ wifi.key_id = -1;
+ memset(ap.ssid.val, 0, sizeof(ap.ssid.val));
+ ap.ssid.len = 0;
+ ap.password = NULL;
+ ap.password_len = 0;
+ ap.channel = 1;
+}
+
+static void print_scan_result( rtw_scan_result_t* record )
+{
+#if CONFIG_EXAMPLE_UART_ATCMD || CONFIG_EXAMPLE_SPI_ATCMD
+ at_printf("%s,%d,%s,%d,"MAC_FMT"", record->SSID.val, record->channel,
+ ( record->security == RTW_SECURITY_OPEN ) ? "Open" :
+ ( record->security == RTW_SECURITY_WEP_PSK ) ? "WEP" :
+ ( record->security == RTW_SECURITY_WPA_TKIP_PSK ) ? "WPA TKIP" :
+ ( record->security == RTW_SECURITY_WPA_AES_PSK ) ? "WPA AES" :
+ ( record->security == RTW_SECURITY_WPA2_AES_PSK ) ? "WPA2 AES" :
+ ( record->security == RTW_SECURITY_WPA2_TKIP_PSK ) ? "WPA2 TKIP" :
+ ( record->security == RTW_SECURITY_WPA2_MIXED_PSK ) ? "WPA2 Mixed" :
+ ( record->security == RTW_SECURITY_WPA_WPA2_MIXED ) ? "WPA/WPA2 AES" : "Unknown",
+ record->signal_strength, MAC_ARG(record->BSSID.octet) );
+#else
+ RTW_API_INFO( ( "%s\t ", ( record->bss_type == RTW_BSS_TYPE_ADHOC ) ? "Adhoc" : "Infra" ) );
+ RTW_API_INFO( ( MAC_FMT, MAC_ARG(record->BSSID.octet) ) );
+ RTW_API_INFO( ( " %d\t ", record->signal_strength ) );
+ RTW_API_INFO( ( " %d\t ", record->channel ) );
+ RTW_API_INFO( ( " %d\t ", record->wps_type ) );
+ RTW_API_INFO( ( "%s\t\t ", ( record->security == RTW_SECURITY_OPEN ) ? "Open" :
+ ( record->security == RTW_SECURITY_WEP_PSK ) ? "WEP" :
+ ( record->security == RTW_SECURITY_WPA_TKIP_PSK ) ? "WPA TKIP" :
+ ( record->security == RTW_SECURITY_WPA_AES_PSK ) ? "WPA AES" :
+ ( record->security == RTW_SECURITY_WPA2_AES_PSK ) ? "WPA2 AES" :
+ ( record->security == RTW_SECURITY_WPA2_TKIP_PSK ) ? "WPA2 TKIP" :
+ ( record->security == RTW_SECURITY_WPA2_MIXED_PSK ) ? "WPA2 Mixed" :
+ ( record->security == RTW_SECURITY_WPA_WPA2_MIXED ) ? "WPA/WPA2 AES" :
+ "Unknown" ) );
+
+ RTW_API_INFO( ( " %s ", record->SSID.val ) );
+ RTW_API_INFO( ( "\r\n" ) );
+#endif
+}
+
+static rtw_result_t app_scan_result_handler( rtw_scan_handler_result_t* malloced_scan_result )
+{
+ static int ApNum = 0;
+
+ if (malloced_scan_result->scan_complete != RTW_TRUE) {
+ rtw_scan_result_t* record = &malloced_scan_result->ap_details;
+ record->SSID.val[record->SSID.len] = 0; /* Ensure the SSID is null terminated */
+
+#if CONFIG_EXAMPLE_UART_ATCMD || CONFIG_EXAMPLE_SPI_ATCMD
+ at_printf("\r\nAP : %d,", ++ApNum);
+#else
+ RTW_API_INFO( ( "%d\t ", ++ApNum ) );
+#endif
+ print_scan_result(record);
+#if CONFIG_INIC_CMD_RSP
+ if(malloced_scan_result->user_data)
+ memcpy((void *)((char *)malloced_scan_result->user_data+(ApNum-1)*sizeof(rtw_scan_result_t)), (char *)record, sizeof(rtw_scan_result_t));
+#endif
+ } else{
+#if CONFIG_INIC_CMD_RSP
+ inic_c2h_msg("ATWS", RTW_SUCCESS, (char *)malloced_scan_result->user_data, ApNum*sizeof(rtw_scan_result_t));
+ if(malloced_scan_result->user_data)
+ free(malloced_scan_result->user_data);
+ inic_c2h_msg("ATWS", RTW_SUCCESS, NULL, 0);
+#endif
+#if CONFIG_EXAMPLE_UART_ATCMD || CONFIG_EXAMPLE_SPI_ATCMD
+ at_printf("\r\n[ATWS] OK");
+ at_printf(STR_END_OF_ATCMD_RET);
+#endif
+ ApNum = 0;
+ }
+ return RTW_SUCCESS;
+}
+
+void fATWD(void *arg){
+ int timeout = 20;
+ char essid[33];
+ int ret = RTW_SUCCESS;
+#if ATCMD_VER == ATVER_2
+ int error_no = 0;
+#endif
+
+ printf("[ATWD]: _AT_WLAN_DISC_NET_\n\r");
+ printf("\n\rDeassociating AP ...");
+
+ if(wext_get_ssid(WLAN0_NAME, (unsigned char *) essid) < 0) {
+ printf("\n\rWIFI disconnected");
+ goto exit_success;
+ }
+#if ATCMD_VER == ATVER_2
+ wifi_unreg_event_handler(WIFI_EVENT_DISCONNECT, atcmd_wifi_disconn_hdl);
+#endif
+ if((ret = wifi_disconnect()) < 0) {
+ printf("[ATWD]ERROR: Operation failed!\n\r");
+#if ATCMD_VER == ATVER_2
+ error_no = 3;
+#endif
+ goto exit;
+ }
+
+ while(1) {
+ if(wext_get_ssid(WLAN0_NAME, (unsigned char *) essid) < 0) {
+ printf("\n\rWIFI disconnected");
+ break;
+ }
+
+ if(timeout == 0) {
+ printf("[ATWD]ERROR: Deassoc timeout!\n\r");
+ ret = RTW_TIMEOUT;
+#if ATCMD_VER == ATVER_2
+ error_no = 4;
+#endif
+ break;
+ }
+
+ vTaskDelay(1 * configTICK_RATE_HZ);
+ timeout --;
+ }
+ printf("\n\r");
+
+#if CONFIG_LWIP_LAYER
+ LwIP_ReleaseIP(WLAN0_IDX);
+#endif
+exit:
+#if CONFIG_INIC_CMD_RSP
+ if(ret != RTW_SUCCESS)
+ inic_c2h_msg("ATWD", ret, NULL, 0);
+#endif
+ init_wifi_struct( );
+#if ATCMD_VER == ATVER_2
+ if(error_no==0)
+ at_printf("\r\n[ATWD] OK");
+ else
+ at_printf("\r\n[ATWD] ERROR:%d",error_no);
+#endif
+ return;
+exit_success:
+#if CONFIG_INIC_CMD_RSP
+ inic_c2h_msg("ATWD", RTW_SUCCESS, NULL, 0);
+#endif
+ init_wifi_struct( );
+#if ATCMD_VER == ATVER_2
+ at_printf("\r\n[ATWD] OK");
+#endif
+ return;
+}
+
+#if (CONFIG_INCLUDE_SIMPLE_CONFIG)
+void fATWQ(void *arg){
+ int argc=0;
+ char *argv[2] = {0};
+ printf("[ATWQ]: _AT_WLAN_SIMPLE_CONFIG_\n\r");
+ argv[argc++] = "wifi_simple_config";
+ if(arg){
+ argv[argc++] = arg;
+ }
+ cmd_simple_config(argc, argv);
+}
+#endif
+
+void fATWS(void *arg){
+ char buf[32] = {0};
+ u8 *channel_list = NULL;
+ u8 *pscan_config = NULL;
+ int num_channel = 0;
+ int i, argc = 0;
+ char *argv[MAX_ARGC] = {0};
+ int ret = RTW_SUCCESS;
+#if CONFIG_INIC_CMD_RSP
+ u8 *inic_scan_buf = NULL;
+#endif
+#if ATCMD_VER == ATVER_2
+ int error_no = 0;
+#endif
+ printf("[ATWS]: _AT_WLAN_SCAN_\n\r");
+ if(arg){
+ strcpy(buf, arg);
+ argc = parse_param(buf, argv);
+ if(argc < 2){
+ ret = RTW_BADARG;
+#if ATCMD_VER == ATVER_2
+ error_no = 1;
+#endif
+ goto exit;
+ }
+ num_channel = atoi(argv[1]);
+ channel_list = (u8*)malloc(num_channel);
+ if(!channel_list){
+ printf("[ATWS]ERROR: Can't malloc memory for channel list\n\r");
+ ret = RTW_BUFFER_UNAVAILABLE_TEMPORARY;
+#if ATCMD_VER == ATVER_2
+ error_no = 2;
+#endif
+ goto exit;
+ }
+ pscan_config = (u8*)malloc(num_channel);
+ if(!pscan_config){
+ printf("[ATWS]ERROR: Can't malloc memory for pscan_config\n\r");
+ ret = RTW_BUFFER_UNAVAILABLE_TEMPORARY;
+#if ATCMD_VER == ATVER_2
+ error_no = 3;
+#endif
+ goto exit;
+ }
+ //parse command channel list
+ for(i = 2; i <= argc -1 ; i++){
+ *(channel_list + i - 2) = (u8)atoi(argv[i]);
+ *(pscan_config + i - 2) = PSCAN_ENABLE;
+ }
+
+ if((ret = wifi_set_pscan_chan(channel_list, pscan_config, num_channel)) < 0){
+ printf("[ATWS]ERROR: wifi set partial scan channel fail\n\r");
+#if ATCMD_VER == ATVER_2
+ error_no = 4;
+#endif
+ goto exit;
+ }
+ }
+#if CONFIG_INIC_CMD_RSP
+ inic_scan_buf = malloc(65*sizeof(rtw_scan_result_t));
+ if(inic_scan_buf == NULL){
+ ret = RTW_BUFFER_UNAVAILABLE_TEMPORARY;
+ goto exit;
+ }
+ memset(inic_scan_buf, 0, 65*sizeof(rtw_scan_result_t));
+ if((ret = wifi_scan_networks(app_scan_result_handler, inic_scan_buf)) != RTW_SUCCESS){
+ printf("[ATWS]ERROR: wifi scan failed\n\r");
+ goto exit;
+ }
+#else
+ if((ret = wifi_scan_networks(app_scan_result_handler, NULL )) != RTW_SUCCESS){
+ printf("[ATWS]ERROR: wifi scan failed\n\r");
+#if ATCMD_VER == ATVER_2
+ error_no = 5;
+#endif
+ goto exit;
+ }
+#endif
+exit:
+#if CONFIG_INIC_CMD_RSP
+ if(ret != RTW_SUCCESS){
+ if(inic_scan_buf)
+ free(inic_scan_buf);
+ inic_c2h_msg("ATWS", ret, NULL, 0);
+ }
+#endif
+#if ATCMD_VER == ATVER_2
+ if(error_no)
+ at_printf("\r\n[ATWS] ERROR:%d",error_no);
+#endif
+ if(arg && channel_list)
+ free(channel_list);
+ if(arg && pscan_config)
+ free(pscan_config);
+}
+
+void fATWx(void *arg){
+ int i = 0;
+#if CONFIG_LWIP_LAYER
+ u8 *mac = LwIP_GetMAC(&xnetif[0]);
+ u8 *ip = LwIP_GetIP(&xnetif[0]);
+ u8 *gw = LwIP_GetGW(&xnetif[0]);
+#endif
+ u8 *ifname[2] = {WLAN0_NAME,WLAN1_NAME};
+ rtw_wifi_setting_t setting;
+
+ printf("[ATW?]: _AT_WLAN_INFO_\n\r");
+#if CONFIG_INIC_CMD_RSP
+ int ret = RTW_SUCCESS;
+ int info_sz = 0;
+ u8 *info = malloc(NET_IF_NUM*sizeof(rtw_wifi_setting_t)+3*sizeof(rtw_mac_t));
+ if(info == NULL)
+ ret = RTW_BUFFER_UNAVAILABLE_TEMPORARY;
+#endif
+ for(i=0;i %02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]) ;
+ printf("\n\r\tIP => %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
+ printf("\n\r\tGW => %d.%d.%d.%d\n\r", gw[0], gw[1], gw[2], gw[3]);
+#endif
+ if(setting.mode == RTW_MODE_AP || i == 1)
+ {
+ int client_number;
+ struct {
+ int count;
+ rtw_mac_t mac_list[AP_STA_NUM];
+ } client_info;
+
+ client_info.count = AP_STA_NUM;
+ wifi_get_associated_client_list(&client_info, sizeof(client_info));
+
+ printf("\n\rAssociated Client List:");
+ printf("\n\r==============================");
+
+ if(client_info.count == 0)
+ printf("\n\rClient Num: 0\n\r", client_info.count);
+ else
+ {
+ printf("\n\rClient Num: %d", client_info.count);
+ for( client_number=0; client_number < client_info.count; client_number++ )
+ {
+ printf("\n\rClient %d:", client_number + 1);
+ printf("\n\r\tMAC => "MAC_FMT"",
+ MAC_ARG(client_info.mac_list[client_number].octet));
+#if CONFIG_EXAMPLE_UART_ATCMD || CONFIG_EXAMPLE_SPI_ATCMD
+ at_printf("\r\nCLIENT : %d,"MAC_FMT"", client_number + 1, MAC_ARG(client_info.mac_list[client_number].octet));
+#endif
+#if CONFIG_INIC_CMD_RSP
+ if(info){
+ memcpy(info+info_sz, (void *)&client_info.mac_list[client_number], sizeof(rtw_mac_t));
+ info_sz += sizeof(rtw_mac_t);
+ }
+#endif
+ }
+ printf("\n\r");
+ }
+ }
+ }
+// show the ethernet interface info
+ else{
+#if CONFIG_ETHERNET
+ if(i == NET_IF_NUM - 1){
+#if CONFIG_LWIP_LAYER
+ mac = LwIP_GetMAC(&xnetif[i]);
+ ip = LwIP_GetIP(&xnetif[i]);
+ gw = LwIP_GetGW(&xnetif[i]);
+ printf("\n\rInterface ethernet\n");
+ printf("\n\r==============================");
+ printf("\n\r\tMAC => %02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]) ;
+ printf("\n\r\tIP => %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
+ printf("\n\r\tGW => %d.%d.%d.%d\n\r", gw[0], gw[1], gw[2], gw[3]);
+#endif // end CONFIG_LWIP_LAYER
+ }
+#endif // end CONFIG_ETHERNET
+ }
+ }
+
+#if defined(configUSE_TRACE_FACILITY) && (configUSE_TRACE_FACILITY == 1) && (configUSE_STATS_FORMATTING_FUNCTIONS == 1)
+ {
+ signed char pcWriteBuffer[1024];
+ vTaskList((char*)pcWriteBuffer);
+ printf("\n\rTask List: \n\r%s", pcWriteBuffer);
+ }
+#endif
+
+#if CONFIG_INIC_CMD_RSP
+ if(ret != RTW_SUCCESS)
+ inic_c2h_msg("ATW?", ret, NULL, 0);
+ else
+ inic_c2h_msg("ATW?", RTW_SUCCESS, (char *)info, info_sz);
+
+ if(info)
+ free(info);
+ info = NULL;
+#endif
+
+#if CONFIG_EXAMPLE_UART_ATCMD || CONFIG_EXAMPLE_SPI_ATCMD
+ at_printf("\r\n[ATW?] OK");
+#endif
+
+}
+
+#if ATCMD_VER == ATVER_1
+void fATW0(void *arg){
+ int ret = RTW_SUCCESS;
+ if(!arg){
+ printf("[ATW0]Usage: ATW0=SSID(Maximum length is 32)\n\r");
+ ret = RTW_BADARG;
+ goto exit;
+ }
+ if(strlen((char*)arg) > 32){
+ printf("[ATW0]Error: SSID length can't exceed 32\n\r");
+ ret = RTW_BADARG;
+ goto exit;
+ }
+ printf("[ATW0]: _AT_WLAN_SET_SSID_ [%s]\n\r", (char*)arg);
+ strcpy((char *)wifi.ssid.val, (char*)arg);
+ wifi.ssid.len = strlen((char*)arg);
+exit:
+#if CONFIG_INIC_CMD_RSP
+ inic_c2h_msg("ATW0", ret, NULL, 0);
+#endif
+ return;
+}
+
+void fATW1(void *arg){
+ int ret = RTW_SUCCESS;
+ printf("[ATW1]: _AT_WLAN_SET_PASSPHRASE_ [%s]\n\r", (char*)arg);
+ strcpy((char *)password, (char*)arg);
+ wifi.password = password;
+ wifi.password_len = strlen((char*)arg);
+exit:
+#if CONFIG_INIC_CMD_RSP
+ inic_c2h_msg("ATW1", ret, NULL, 0);
+#endif
+ return;
+}
+
+void fATW2(void *arg){
+ int ret = RTW_SUCCESS;
+ printf("[ATW2]: _AT_WLAN_SET_KEY_ID_ [%s]\n\r", (char*)arg);
+ if((strlen((const char *)arg) != 1 ) || (*(char*)arg <'0' ||*(char*)arg >'3')) {
+ printf("[ATW2]Error: Wrong WEP key id. Must be one of 0,1,2, or 3.\n\r");
+ ret = RTW_BADARG;
+ goto exit;
+ }
+ wifi.key_id = atoi((const char *)(arg));
+exit:
+#if CONFIG_INIC_CMD_RSP
+ inic_c2h_msg("ATW2", ret, NULL, 0);
+#endif
+ return;
+}
+
+void fATW3(void *arg){
+ int ret = RTW_SUCCESS;
+ if(!arg){
+ printf("[ATW3]Usage: ATW3=SSID\n\r");
+ ret = RTW_BADARG;
+ goto exit;
+ }
+ if(strlen((char*)arg) > 32){
+ printf("[ATW3]Error: SSID length can't exceed 32\n\r");
+ ret = RTW_BADARG;
+ goto exit;
+ }
+ strcpy((char *)ap.ssid.val, (char*)arg);
+ ap.ssid.len = strlen((char*)arg);
+
+ printf("[ATW3]: _AT_WLAN_AP_SET_SSID_ [%s]\n\r", ap.ssid.val);
+exit:
+#if CONFIG_INIC_CMD_RSP
+ inic_c2h_msg("ATW3", ret, NULL, 0);
+#endif
+ return;
+}
+
+void fATW4(void *arg){
+ int ret = RTW_SUCCESS;
+
+ if(!arg){
+ printf("[ATW4]Usage: ATW4=PASSWORD\n\r");
+ ret = RTW_BADARG;
+ goto exit;
+ }
+ if(strlen((char*)arg) > 64){
+ printf("[ATW4]Error: PASSWORD length can't exceed 64\n\r");
+ ret = RTW_BADARG;
+ goto exit;
+ }
+
+ strcpy((char *)password, (char*)arg);
+ ap.password = password;
+ ap.password_len = strlen((char*)arg);
+ printf("[ATW4]: _AT_WLAN_AP_SET_SEC_KEY_ [%s]\n\r", ap.password);
+exit:
+#if CONFIG_INIC_CMD_RSP
+ inic_c2h_msg("ATW4", ret, NULL, 0);
+#endif
+ return;
+}
+
+void fATW5(void *arg){
+ int ret = RTW_SUCCESS;
+ if(!arg){
+ printf("[ATW5]Usage: ATW5=CHANNEL\n\r");
+ ret = RTW_BADARG;
+ goto exit;
+ }
+ ap.channel = (unsigned char) atoi((const char *)arg);
+ printf("[ATW5]: _AT_WLAN_AP_SET_CHANNEL_ [channel %d]\n\r", ap.channel);
+exit:
+#if CONFIG_INIC_CMD_RSP
+ inic_c2h_msg("ATW5", ret, NULL, 0);
+#endif
+ return;
+}
+
+void fATW6(void *arg){
+ u32 mac[ETH_ALEN];
+ u32 i;
+ int ret = RTW_SUCCESS;
+ if(!arg){
+ printf("[ATW6]Usage: ATW6=BSSID\n\r");
+ ret = RTW_BADARG;
+ goto exit;
+ }
+ printf("[ATW6]: _AT_WLAN_SET_BSSID_ [%s]\n\r", (char*)arg);
+ sscanf(arg, MAC_FMT, mac, mac + 1, mac + 2, mac + 3, mac + 4, mac + 5);
+ for(i = 0; i < ETH_ALEN; i ++)
+ wifi.bssid.octet[i] = (u8)mac[i] & 0xFF;
+exit:
+#if CONFIG_INIC_CMD_RSP
+ inic_c2h_msg("ATW6", ret, NULL, 0);
+#endif
+ return;
+}
+
+void fATWA(void *arg){
+#if CONFIG_LWIP_LAYER
+ struct ip_addr ipaddr;
+ struct ip_addr netmask;
+ struct ip_addr gw;
+ struct netif * pnetif = &xnetif[0];
+#endif
+ int timeout = 20;
+ int ret = RTW_SUCCESS;
+ printf("[ATWA]: _AT_WLAN_AP_ACTIVATE_\n\r");
+ if(ap.ssid.val[0] == 0){
+ printf("[ATWA]Error: SSID can't be empty\n\r");
+ ret = RTW_BADARG;
+ goto exit;
+ }
+ if(ap.password == NULL){
+ ap.security_type = RTW_SECURITY_OPEN;
+ }
+ else{
+ if(ap.password_len <= RTW_MAX_PSK_LEN &&
+ ap.password_len >= RTW_MIN_PSK_LEN){
+ ap.security_type = RTW_SECURITY_WPA2_AES_PSK;
+ }
+ else{
+ printf("[ATWA]Error: password length is between 8 to 64 \n\r");
+ ret = RTW_INVALID_KEY;
+ goto exit;
+ }
+ }
+
+#if CONFIG_WEBSERVER
+ //store into flash
+ memset(wifi_setting.ssid, 0, sizeof(wifi_setting.ssid));;
+ memcpy(wifi_setting.ssid, ap.ssid.val, strlen((char*)ap.ssid.val));
+ wifi_setting.ssid[ap.ssid.len] = '\0';
+ wifi_setting.security_type = ap.security_type;
+ if(ap.security_type !=0)
+ wifi_setting.security_type = 1;
+ else
+ wifi_setting.security_type = 0;
+ if (ap.password)
+ memcpy(wifi_setting.password, ap.password, strlen((char*)ap.password));
+ else
+ memset(wifi_setting.password, 0, sizeof(wifi_setting.password));
+ wifi_setting.channel = ap.channel;
+#if CONFIG_READ_FLASH
+ StoreApInfo();
+#endif
+#endif
+
+#if CONFIG_LWIP_LAYER
+ dhcps_deinit();
+ IP4_ADDR(&ipaddr, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
+ IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1 , NETMASK_ADDR2, NETMASK_ADDR3);
+ IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
+ netif_set_addr(pnetif, &ipaddr, &netmask,&gw);
+#ifdef CONFIG_DONT_CARE_TP
+ pnetif->flags |= NETIF_FLAG_IPSWITCH;
+#endif
+#endif
+ wifi_off();
+ vTaskDelay(20);
+ if (wifi_on(RTW_MODE_AP) < 0){
+ printf("\n\rERROR: Wifi on failed!");
+ ret = RTW_ERROR;
+ goto exit;
+ }
+ printf("\n\rStarting AP ...");
+
+#if defined(CONFIG_ENABLE_WPS_AP) && CONFIG_ENABLE_WPS_AP
+ wpas_wps_dev_config(pnetif->hwaddr, 1);
+#endif
+ if((ret = wifi_start_ap((char*)ap.ssid.val, ap.security_type, (char*)ap.password,/* ap.ssid.len, ap.password_len,*/ ap.channel, 0) )< 0) {
+ printf("\n\rERROR: Operation failed!");
+ goto exit;
+ }
+
+ while(1) {
+ char essid[33];
+
+ if(wext_get_ssid(WLAN0_NAME, (unsigned char *) essid) > 0) {
+ if(strcmp((const char *) essid, (const char *)ap.ssid.val) == 0) {
+ printf("\n\r%s started\n", ap.ssid.val);
+ ret = RTW_SUCCESS;
+ break;
+ }
+ }
+
+ if(timeout == 0) {
+ printf("\n\rERROR: Start AP timeout!");
+ ret = RTW_TIMEOUT;
+ break;
+ }
+
+ vTaskDelay(1 * configTICK_RATE_HZ);
+ timeout --;
+ }
+
+#if defined( CONFIG_ENABLE_AP_POLLING_CLIENT_ALIVE )&&( CONFIG_ENABLE_AP_POLLING_CLIENT_ALIVE == 1 )
+ wifi_set_ap_polling_sta(1);
+#endif
+
+#if CONFIG_LWIP_LAYER
+ //LwIP_UseStaticIP(pnetif);
+ dhcps_init(pnetif);
+#endif
+
+exit:
+#if CONFIG_INIC_CMD_RSP
+ inic_c2h_wifi_info("ATWA", ret);
+#endif
+ init_wifi_struct( );
+}
+
+#if CONFIG_INIC_EN
+static int _find_ap_from_scan_buf(char*buf, int buflen, char *target_ssid, void *user_data)
+{
+ rtw_wifi_setting_t *pwifi = (rtw_wifi_setting_t *)user_data;
+ int plen = 0;
+
+ while(plen < buflen){
+ u8 len, ssid_len, security_mode;
+ char *ssid;
+
+ // len offset = 0
+ len = (int)*(buf + plen);
+ // check end
+ if(len == 0) break;
+ // ssid offset = 14
+ ssid_len = len - 14;
+ ssid = buf + plen + 14 ;
+ if((ssid_len == strlen(target_ssid))
+ && (!memcmp(ssid, target_ssid, ssid_len)))
+ {
+ strcpy((char*)pwifi->ssid, target_ssid);
+ // channel offset = 13
+ pwifi->channel = *(buf + plen + 13);
+ // security_mode offset = 11
+ security_mode = (u8)*(buf + plen + 11);
+ if(security_mode == IW_ENCODE_ALG_NONE)
+ pwifi->security_type = RTW_SECURITY_OPEN;
+ else if(security_mode == IW_ENCODE_ALG_WEP)
+ pwifi->security_type = RTW_SECURITY_WEP_PSK;
+ else if(security_mode == IW_ENCODE_ALG_CCMP)
+ pwifi->security_type = RTW_SECURITY_WPA2_AES_PSK;
+ break;
+ }
+ plen += len;
+ }
+ return 0;
+}
+
+static int _get_ap_security_mode(IN char * ssid, OUT rtw_security_t *security_mode, OUT u8 * channel)
+{
+ rtw_wifi_setting_t wifi;
+ u32 scan_buflen = 1000;
+
+ memset(&wifi, 0, sizeof(wifi));
+
+ if(wifi_scan_networks_with_ssid(_find_ap_from_scan_buf, (void*)&wifi, scan_buflen, ssid, strlen(ssid)) != RTW_SUCCESS){
+ printf("Wifi scan failed!\n");
+ return 0;
+ }
+
+ if(strcmp(wifi.ssid, ssid) == 0){
+ *security_mode = wifi.security_type;
+ *channel = wifi.channel;
+ return 1;
+ }
+
+ return 0;
+}
+#endif
+
+void fATWC(void *arg){
+ int mode, ret;
+ unsigned long tick1 = xTaskGetTickCount();
+ unsigned long tick2, tick3;
+ char empty_bssid[6] = {0}, assoc_by_bssid = 0;
+
+ printf("[ATWC]: _AT_WLAN_JOIN_NET_\n\r");
+ if(memcmp (wifi.bssid.octet, empty_bssid, 6))
+ assoc_by_bssid = 1;
+ else if(wifi.ssid.val[0] == 0){
+ printf("[ATWC]Error: SSID can't be empty\n\r");
+ ret = RTW_BADARG;
+ goto EXIT;
+ }
+ if(wifi.password != NULL){
+ if((wifi.key_id >= 0)&&(wifi.key_id <= 3)) {
+ wifi.security_type = RTW_SECURITY_WEP_PSK;
+ }
+ else{
+ wifi.security_type = RTW_SECURITY_WPA2_AES_PSK;
+ }
+ }
+ else{
+ wifi.security_type = RTW_SECURITY_OPEN;
+ }
+ //Check if in AP mode
+ wext_get_mode(WLAN0_NAME, &mode);
+ if(mode == IW_MODE_MASTER) {
+#if CONFIG_LWIP_LAYER
+ dhcps_deinit();
+#endif
+ wifi_off();
+ vTaskDelay(20);
+ if (wifi_on(RTW_MODE_STA) < 0){
+ printf("\n\rERROR: Wifi on failed!");
+ ret = RTW_ERROR;
+ goto EXIT;
+ }
+ }
+
+#if CONFIG_INIC_EN //get security mode from scan list
+ u8 connect_channel;
+ u8 pscan_config;
+ //the keyID may be not set for WEP which may be confued with WPA2
+ if((wifi.security_type == RTW_SECURITY_UNKNOWN)||(wifi.security_type == RTW_SECURITY_WPA2_AES_PSK))
+ {
+ int security_retry_count = 0;
+ while (1) {
+ if (_get_ap_security_mode((char*)wifi.ssid.val, &wifi.security_type, &connect_channel))
+ break;
+ security_retry_count++;
+ if(security_retry_count >= 3){
+ printf("Can't get AP security mode and channel.\n");
+ ret = RTW_NOTFOUND;
+ goto EXIT;
+ }
+ }
+ if(wifi.security_type == RTW_SECURITY_WEP_PSK || wifi.security_type == RTW_SECURITY_WEP_SHARED)
+ wifi.key_id = (wifi.key_id <0 || wifi.key_id >3)?0:wifi.key_id;
+#if 0 //implemented in wifi_connect()
+ //hex to ascii conversion
+ if(wifi.security_type == RTW_SECURITY_WEP_PSK)
+ {
+ if(wifi.password_len == 10)
+ {
+ u32 p[5];
+ u8 pwd[6], i = 0;
+ sscanf((const char*)wifi.password, "%02x%02x%02x%02x%02x", &p[0], &p[1], &p[2], &p[3], &p[4]);
+ for(i=0; i< 5; i++)
+ pwd[i] = (u8)p[i];
+ pwd[5] = '\0';
+ memset(wifi.password, 0, 65);
+ strcpy((char*)wifi.password, (char*)pwd);
+ wifi.password_len = 5;
+ }else if(wifi.password_len == 26){
+ u32 p[13];
+ u8 pwd[14], i = 0;
+ sscanf((const char*)wifi.password, "%02x%02x%02x%02x%02x%02x%02x"\
+ "%02x%02x%02x%02x%02x%02x", &p[0], &p[1], &p[2], &p[3], &p[4],\
+ &p[5], &p[6], &p[7], &p[8], &p[9], &p[10], &p[11], &p[12]);
+ for(i=0; i< 13; i++)
+ pwd[i] = (u8)p[i];
+ pwd[13] = '\0';
+ memset(wifi.password, 0, 65);
+ strcpy((char*)wifi.password, (char*)pwd);
+ wifi.password_len = 13;
+ }
+ }
+#endif
+ }
+ pscan_config = PSCAN_ENABLE;
+ if(connect_channel > 0 && connect_channel < 14)
+ wifi_set_pscan_chan(&connect_channel, &pscan_config, 1);
+#endif
+
+ if(assoc_by_bssid){
+ printf("\n\rJoining BSS by BSSID "MAC_FMT" ...\n\r", MAC_ARG(wifi.bssid.octet));
+ } else {
+ printf("\n\rJoining BSS by SSID %s...\n\r", (char*)wifi.ssid.val);
+ }
+ ret = wifi_connect(wifi.bssid.octet,
+ assoc_by_bssid,
+ (char*)wifi.ssid.val,
+ wifi.security_type,
+ (char*)wifi.password,
+ wifi.key_id,
+ NULL);
+
+ if(ret!= RTW_SUCCESS){
+ if(ret == RTW_INVALID_KEY)
+ printf("\n\rERROR:Invalid Key ");
+
+ printf("\n\rERROR: Can't connect to AP");
+ goto EXIT;
+ }
+ tick2 = xTaskGetTickCount();
+ printf("\r\nConnected after %dms.\n", (tick2-tick1));
+#if CONFIG_LWIP_LAYER
+ /* Start DHCPClient */
+ LwIP_DHCP(0, DHCP_START);
+ tick3 = xTaskGetTickCount();
+ printf("\r\n\nGot IP after %dms.\n", (tick3-tick1));
+#endif
+ printf("\n\r");
+EXIT:
+#if CONFIG_INIC_CMD_RSP
+ inic_c2h_wifi_info("ATWC", ret);
+#endif
+
+ init_wifi_struct( );
+}
+
+#if SCAN_WITH_SSID
+void fATWs(void *arg){
+ char buf[32] = {0};
+ u8 *channel_list = NULL;
+ u8 *pscan_config = NULL;
+ int scan_buf_len = 500;
+ int num_channel = 0;
+ int i, argc = 0;
+ char *argv[MAX_ARGC] = {0};
+ printf("[ATWs]: _AT_WLAN_SCAN_WITH_SSID_ [%s]\n\r", (char*)wifi.ssid.val);
+ if(arg){
+ strcpy(buf, arg);
+ argc = parse_param(buf, argv);
+ if(argc == 2){
+ scan_buf_len = atoi(argv[1]);
+ if(scan_buf_len < 36){
+ printf("[ATWs] BUFFER_LENGTH too short\n\r");
+ goto exit;
+ }
+ }else if(argc > 2){
+ num_channel = atoi(argv[1]);
+ channel_list = (u8*)malloc(num_channel);
+ if(!channel_list){
+ printf("[ATWs]ERROR: Can't malloc memory for channel list\n\r");
+ goto exit;
+ }
+ pscan_config = (u8*)malloc(num_channel);
+ if(!pscan_config){
+ printf("[ATWs]ERROR: Can't malloc memory for pscan_config\n\r");
+ goto exit;
+ }
+ //parse command channel list
+ for(i = 2; i <= argc -1 ; i++){
+ *(channel_list + i - 2) = (u8)atoi(argv[i]);
+ *(pscan_config + i - 2) = PSCAN_ENABLE;
+ }
+
+ if(wifi_set_pscan_chan(channel_list, pscan_config, num_channel) < 0){
+ printf("[ATWs]ERROR: wifi set partial scan channel fail\n\r");
+ goto exit;
+ }
+ }
+ }else{
+ printf("[ATWs]For Scan all channel Usage: ATWs=BUFFER_LENGTH\n\r");
+ printf("[ATWs]For Scan partial channel Usage: ATWs=num_channels[channel_num1, ...]\n\r");
+ goto exit;
+ }
+
+ if(wifi_scan_networks_with_ssid(NULL, NULL, scan_buf_len, (char*)wifi.ssid.val, wifi.ssid.len) != RTW_SUCCESS){
+ printf("[ATWs]ERROR: wifi scan failed\n\r");
+ }
+exit:
+ init_wifi_struct( );
+ if(arg && channel_list)
+ free(channel_list);
+ if(arg && pscan_config)
+ free(pscan_config);
+}
+#endif
+
+void fATWR(void *arg){
+ int rssi = 0;
+ printf("[ATWR]: _AT_WLAN_GET_RSSI_\n\r");
+ wifi_get_rssi(&rssi);
+ printf("\n\rwifi_get_rssi: rssi = %d", rssi);
+ printf("\n\r");
+}
+
+void fATWP(void *arg){
+ unsigned int parm = atoi((const char *)(arg));
+ printf("[ATWP]: _AT_WLAN_POWER_[%s]\n\r", parm?"ON":"OFF");
+ if(parm == 1){
+ if(wifi_on(RTW_MODE_STA)<0){
+ printf("\n\rERROR: Wifi on failed!\n");
+ }
+ }
+ else if(parm == 0)
+ {
+#if CONFIG_WEBSERVER
+ stop_web_server();
+#endif
+ wifi_off();
+ }
+ else
+ printf("[ATWP]Usage: ATWP=0/1\n\r");
+}
+
+#if CONFIG_WOWLAN_SERVICE
+//for wowlan setting
+void fATWV(void *arg){
+ int argc;
+ char *argv[MAX_ARGC] = {0};
+
+ printf("[ATWV]: _AT_WLAN_WOWLAN_\r\n");
+
+ argc = parse_param(arg, argv);
+
+ cmd_wowlan_service(argc, argv);
+
+ return;
+}
+#endif
+
+#ifdef CONFIG_CONCURRENT_MODE
+void fATWB(void *arg)
+{
+ int timeout = 20;//, mode;
+ int ret = RTW_SUCCESS;
+#if CONFIG_LWIP_LAYER
+ struct netif * pnetiff = (struct netif *)&xnetif[1];
+#endif
+ printf("[ATWB](_AT_WLAN_AP_STA_ACTIVATE_)\n\r");
+ if(ap.ssid.val[0] == 0){
+ printf("[ATWB]Error: SSID can't be empty\n\r");
+ ret = RTW_BADARG;
+ goto exit;
+ }
+ if(ap.channel > 14){
+ printf("[ATWB]Error:bad channel! channel is from 1 to 14\n\r");
+ ret = RTW_BADARG;
+ goto exit;
+ }
+ if(ap.password == NULL){
+ ap.security_type = RTW_SECURITY_OPEN;
+ }
+ else{
+ ap.security_type = RTW_SECURITY_WPA2_AES_PSK;
+ }
+
+#if CONFIG_WEBSERVER
+ //store into flash
+ memset(wifi_setting.ssid, 0, sizeof(wifi_setting.ssid));;
+ memcpy(wifi_setting.ssid, ap.ssid.val, strlen((char*)ap.ssid.val));
+ wifi_setting.ssid[ap.ssid.len] = '\0';
+ wifi_setting.security_type = ap.security_type;
+ if(ap.security_type !=0)
+ wifi_setting.security_type = 1;
+ else
+ wifi_setting.security_type = 0;
+ if (ap.password)
+ memcpy(wifi_setting.password, ap.password, strlen((char*)ap.password));
+ else
+ memset(wifi_setting.password, 0, sizeof(wifi_setting.password));;
+ wifi_setting.channel = ap.channel;
+#if CONFIG_READ_FLASH
+ StoreApInfo();
+#endif
+#endif
+
+#if CONFIG_LWIP_LAYER
+ dhcps_deinit();
+#endif
+
+ wifi_off();
+ vTaskDelay(20);
+ if ((ret = wifi_on(RTW_MODE_STA_AP)) < 0){
+ printf("\n\rERROR: Wifi on failed!");
+ ret = RTW_ERROR;
+ goto exit;
+ }
+
+ printf("\n\rStarting AP ...");
+ if((ret = wifi_start_ap((char*)ap.ssid.val, ap.security_type, (char*)ap.password, /*ap.ssid.len, ap.password_len,*/ ap.channel, 0)) < 0) {
+ printf("\n\rERROR: Operation failed!");
+ goto exit;
+ }
+ while(1) {
+ char essid[33];
+
+ if(wext_get_ssid(WLAN1_NAME, (unsigned char *) essid) > 0) {
+ if(strcmp((const char *) essid, (const char *)ap.ssid.val) == 0) {
+ printf("\n\r%s started\n", ap.ssid.val);
+ ret = RTW_SUCCESS;
+ break;
+ }
+ }
+
+ if(timeout == 0) {
+ printf("\n\rERROR: Start AP timeout!");
+ ret = RTW_TIMEOUT;
+ break;
+ }
+
+ vTaskDelay(1 * configTICK_RATE_HZ);
+ timeout --;
+ }
+#if CONFIG_LWIP_LAYER
+ LwIP_UseStaticIP(&xnetif[1]);
+#ifdef CONFIG_DONT_CARE_TP
+ pnetiff->flags |= NETIF_FLAG_IPSWITCH;
+#endif
+ dhcps_init(pnetiff);
+#endif
+
+#if defined( CONFIG_ENABLE_AP_POLLING_CLIENT_ALIVE )&&( CONFIG_ENABLE_AP_POLLING_CLIENT_ALIVE == 1 )
+ wifi_set_ap_polling_sta(1);
+#endif
+exit:
+#if CONFIG_INIC_CMD_RSP
+ inic_c2h_wifi_info("ATWB", ret);
+#endif
+ init_wifi_struct();
+}
+#endif
+
+#ifdef CONFIG_PROMISC
+void fATWM(void *arg){
+ int argc;
+ char *argv[MAX_ARGC] = {0};
+ argv[0] = "wifi_promisc";
+ printf("[ATWM]: _AT_WLAN_PROMISC_\n\r");
+ if(!arg){
+ printf("[ATWM]Usage: ATWM=DURATION_SECONDS[with_len]");
+#if CONFIG_INIC_CMD_RSP
+ inic_c2h_msg("ATWM", RTW_BADARG, NULL, 0);
+#endif
+ return;
+ }
+ if((argc = parse_param(arg, argv)) > 1){
+ cmd_promisc(argc, argv);
+ }
+}
+#endif
+
+#if CONFIG_WEBSERVER
+void fATWE(void *arg){
+ printf("[ATWE]: _AT_WLAN_START_WEB_SERVER_\n\r");
+ start_web_server();
+}
+#endif
+
+void fATWW(void *arg){
+#if CONFIG_ENABLE_WPS
+ int argc = 0;
+ char *argv[4];
+ printf("[ATWW]: _AT_WLAN_WPS_\n\r");
+ if(!arg){
+ printf("[ATWW]Usage: ATWW=pbc/pin\n\r");
+#if CONFIG_INIC_CMD_RSP
+ inic_c2h_msg("ATWW", RTW_BADARG, NULL, 0);
+#endif
+ return;
+ }
+ argv[argc++] = "wifi_wps";
+ argv[argc++] = arg;
+ cmd_wps(argc, argv);
+#else
+ printf("Please set CONFIG_ENABLE_WPS 1 in platform_opts.h to enable ATWW command\n");
+#endif
+}
+void fATWw(void *arg){
+#if defined(CONFIG_ENABLE_WPS_AP) && CONFIG_ENABLE_WPS_AP
+ int argc = 0;
+ char *argv[4];
+ printf("[ATWw]: _AT_WLAN_AP_WPS_\n\r");
+ if(!arg){
+ printf("[ATWw]Usage: ATWw=pbc/pin\n\r");
+ return;
+ }
+ argv[argc++] = "wifi_ap_wps";
+ argv[argc++] = arg;
+ cmd_ap_wps(argc, argv);
+#endif
+}
+
+#if CONFIG_ENABLE_P2P
+void fATWG(void *arg){
+ int argc = 0;
+ char *argv[4];
+ printf("[ATWG]: _AT_WLAN_P2P_START_\n\r");
+ argv[argc++] = "p2p_start";
+ cmd_wifi_p2p_start(argc, argv);
+}
+
+void fATWg(void *arg){
+ int argc = 0;
+ char *argv[4];
+ int ret =0;
+ printf("[ATWg]: _AT_WLAN_P2P_AUTO_GO_START_\n\r");
+ argv[argc++] = "p2p_auto_go_start";
+ ret = cmd_wifi_p2p_auto_go_start(argc, argv);
+ if(ret < 0)
+ printf("\r\n[ATWG]: Nothing to do. Please enter ATWG to initialize P2P.\n\r");
+}
+
+void fATWH(void *arg){
+ int argc = 0;
+ char *argv[4];
+ printf("[ATWH]: _AT_WLAN_P2P_STOP_\n\r");
+ argv[argc++] = "p2p_stop";
+ cmd_wifi_p2p_stop(argc, argv);
+}
+void fATWJ(void *arg){
+ int argc = 0;
+ char *argv[4];
+ printf("[ATWJ]: _AT_WLAN_P2P_CONNECT_\n\r");
+ argv[0] = "p2p_connect";
+ if(!arg){
+ printf("ATWc=[DEST_MAC,pbc/pin]\n\r");
+ return;
+ }
+ if((argc = parse_param(arg, argv)) > 1){
+ cmd_p2p_connect(argc, argv);
+ }
+}
+void fATWK(void *arg){
+ int argc = 0;
+ char *argv[4];
+ printf("[ATWK]: _AT_WLAN_P2P_DISCONNECT_\n\r");
+ argv[argc++] = "p2p_disconnect";
+ cmd_p2p_disconnect(argc, argv);
+}
+void fATWN(void *arg){
+ int argc = 0;
+ char *argv[4];
+ printf("[ATWN]: _AT_WLAN_P2P_INFO_\n\r");
+ argv[argc++] = "p2p_info";
+ cmd_p2p_info(argc, argv);
+}
+void fATWF(void *arg){
+ int argc = 0;
+ char *argv[4];
+ printf("[ATWF]: _AT_WLAN_P2P_FIND_\n\r");
+ argv[argc++] = "p2p_find";
+ cmd_p2p_find(argc, argv);
+}
+#endif
+#if CONFIG_OTA_UPDATE
+void fATWO(void *arg){
+ int argc = 0;
+ char *argv[MAX_ARGC] = {0};
+ printf("[ATWO]: _AT_WLAN_OTA_UPDATE_\n\r");
+ if(!arg){
+ printf("[ATWO]Usage: ATWO=IP[PORT] or ATWO= REPOSITORY[FILE_PATH]\n\r");
+ return;
+ }
+ argv[0] = "update";
+ if((argc = parse_param(arg, argv)) != 3){
+ printf("[ATWO]Usage: ATWO=IP[PORT] or ATWO= REPOSITORY[FILE_PATH]\n\r");
+ return;
+ }
+ cmd_update(argc, argv);
+}
+#endif
+
+#if CONFIG_AIRKISS
+void fATWX(void *arg)
+{
+ int ret = RTW_SUCCESS;
+
+ ret = airkiss_start(NULL);
+#if CONFIG_INIC_CMD_RSP
+ if(ret != RTW_SUCCESS)
+ inic_c2h_msg("ATWX", RTW_ERROR, NULL, 0);
+#endif
+}
+#endif
+
+void fATWZ(void *arg){
+ char buf[32] = {0};
+ char *copy = buf;
+ int i = 0;
+ int len = 0;
+ int ret = RTW_SUCCESS;
+
+ printf("[ATWZ]: _AT_WLAN_IWPRIV_\n\r");
+ if(!arg){
+ printf("[ATWZ]Usage: ATWZ=COMMAND[PARAMETERS]\n\r");
+ ret = RTW_BADARG;
+ goto exit;
+ }
+ strcpy(copy, arg);
+ len = strlen(copy);
+ do{
+ if((*(copy+i)=='['))
+ *(copy+i)=' ';
+ if((*(copy+i)==']')||(*(copy+i)=='\0')){
+ *(copy+i)='\0';
+ break;
+ }
+ }while((i++) < len);
+
+ i = 0;
+ do{
+ if((*(copy+i)==',')) {
+ *(copy+i)=' ';
+ break;
+ }
+ }while((i++) < len);
+
+#if CONFIG_INIC_CMD_RSP
+ ret = wext_private_command_with_retval(WLAN0_NAME, copy, buf, 32);
+ printf("\n\rPrivate Message: %s", (char *) buf);
+ if(ret == RTW_SUCCESS)
+ inic_c2h_msg("ATWZ", ret, buf, strlen(buf));
+#else
+ wext_private_command(WLAN0_NAME, copy, 1);
+#endif
+exit:
+#if CONFIG_INIC_CMD_RSP
+ if(ret != RTW_SUCCESS)
+ inic_c2h_msg("ATWZ", ret, NULL, 0);
+#endif
+ return; // exit label cannot be last statement
+}
+
+#ifdef CONFIG_POWER_SAVING
+void fATXP(void *arg)
+{
+ int argc = 0;
+ char *argv[MAX_ARGC] = {0};
+ int ret = 0;
+ int mode, dtim;
+ int tdma_slot_period, tdma_rfon_period_len_1, tdma_rfon_period_len_2, tdma_rfon_period_len_3;
+#if CONFIG_INIC_CMD_RSP
+ char *res = NULL;
+ int res_len = 0;
+#endif
+
+ printf("[ATXP]: _AT_WLAN_POWER_MODE_\r\n");
+
+ if (!arg) {
+ printf("[ATXP] Usage: ATXP=lps/ips/dtim/tdma[mode]\r\n");
+ ret = RTW_BADARG;
+ goto exit;
+ } else {
+ argc = parse_param(arg, argv);
+ if (argc < 3) {
+ printf("[ATXP] Usage: ATXP=lps/ips/dtim/tdma[mode]\r\n");
+ ret = RTW_BADARG;
+ goto exit;
+ }
+ }
+
+ if (strcmp(argv[1], "lps") == 0) {
+ mode = atoi(argv[2]);
+ if (mode >= 0 && mode < 0xFF) {
+ printf("lps mode:%d\r\n", mode);
+ wifi_set_power_mode(0xff, mode);
+ }
+ }
+
+ if (strcmp(argv[1], "ips") == 0) {
+ mode = atoi(argv[2]);
+ if (mode >= 0 && mode < 0xFF) {
+ printf("ips mode:%d\r\n", mode);
+ wifi_set_power_mode(mode, 0xFF);
+ }
+ }
+
+ if (strcmp(argv[1], "tdma") == 0) {
+ if (argc >= 6) {
+ tdma_slot_period = atoi(argv[2]);
+ tdma_rfon_period_len_1 = atoi(argv[3]);
+ tdma_rfon_period_len_2 = atoi(argv[4]);
+ tdma_rfon_period_len_3 = atoi(argv[5]);
+ printf("tdma param: %d %d %d %d\r\n", tdma_slot_period, tdma_rfon_period_len_1, tdma_rfon_period_len_2, tdma_rfon_period_len_3);
+ wifi_set_tdma_param(tdma_slot_period, tdma_rfon_period_len_1, tdma_rfon_period_len_2, tdma_rfon_period_len_3);
+ }
+ }
+
+ if (strcmp(argv[1], "dtim") == 0) {
+ dtim = atoi(argv[2]);
+ printf("dtim: %d\r\n", dtim);
+ wifi_set_lps_dtim(dtim);
+ }
+
+ if (strcmp(argv[1], "get") == 0) {
+#if CONFIG_INIC_CMD_RSP
+ char buf[32];
+ int index = 0;
+ memset(buf, 0, sizeof(buf));
+ snprintf(buf, 32, "%s,%s,", argv[1], argv[2]);
+ index = strlen(buf);
+#endif
+ if(strcmp(argv[2], "dtim") == 0){
+ wifi_get_lps_dtim((unsigned char *)&dtim);
+ printf("get dtim: %d\r\n", (unsigned char)dtim);
+#if CONFIG_INIC_CMD_RSP
+ sprintf(buf+index, "0x%02x", (unsigned char)dtim);
+ res = (char *)buf;
+ res_len = strlen(buf);
+#endif
+ }
+ }
+
+exit:
+#if CONFIG_INIC_CMD_RSP
+ inic_c2h_msg("ATXP", ret, res, res_len);
+ res = NULL;
+ res_len = 0;
+#endif
+ return;
+}
+#endif
+
+void print_wlan_help(void *arg){
+ printf("\n\rWLAN AT COMMAND SET:");
+ printf("\n\r==============================");
+ printf("\n\r1. Wlan Scan for Network Access Point");
+ printf("\n\r # ATWS");
+ printf("\n\r2. Connect to an AES AP");
+ printf("\n\r # ATW0=SSID");
+ printf("\n\r # ATW1=PASSPHRASE");
+ printf("\n\r # ATWC");
+ printf("\n\r3. Create an AES AP");
+ printf("\n\r # ATW3=SSID");
+ printf("\n\r # ATW4=PASSPHRASE");
+ printf("\n\r # ATW5=CHANNEL");
+ printf("\n\r # ATWA");
+ printf("\n\r4. Ping");
+ printf("\n\r # ATWI=xxx.xxx.xxx.xxx");
+}
+
+#if WIFI_LOGO_CERTIFICATION_CONFIG
+void fATPE(void *arg)
+{
+ int argc, error_no = 0;
+ char *argv[MAX_ARGC] = {0};
+ unsigned int ip_addr = 0;
+ //unsigned char sta_ip[4] = {192,168,3,80}, sta_netmask[4] = {255,255,255,0}, sta_gw[4] = {192,168,3,1};
+
+ if(!arg){
+ AT_DBG_MSG(AT_FLAG_WIFI, AT_DBG_ERROR,
+ "\r\n[ATPE] Usage : ATPE=(,,)");
+ error_no = 1;
+ goto exit;
+ }
+
+ argc = parse_param(arg, argv);
+ if( (argc > 4) || (argc < 2) ){
+ //at_printf("\r\n[ATPE] ERROR : command format error");
+ error_no = 1;
+ goto exit;
+ }
+
+ if(argv[1] != NULL){
+ ip_addr = inet_addr(argv[1]);
+ sta_ip[0] = (unsigned char) ip_addr & 0xff;
+ sta_ip[1] = (unsigned char) (ip_addr >> 8) & 0xff;
+ sta_ip[2] = (unsigned char) (ip_addr >> 16) & 0xff;
+ sta_ip[3] = (unsigned char) (ip_addr >> 24) & 0xff;
+ }
+ else{
+ //at_printf("\r\n[ATPE] ERROR : parameter format error");
+ error_no = 2;
+ goto exit;
+ }
+
+ if(argv[2] != NULL){
+ ip_addr = inet_addr(argv[2]);
+ sta_gw[0] = (unsigned char) ip_addr & 0xff;
+ sta_gw[1] = (unsigned char) (ip_addr >> 8) & 0xff;
+ sta_gw[2] = (unsigned char) (ip_addr >> 16) & 0xff;
+ sta_gw[3] = (unsigned char) (ip_addr >> 24) & 0xff;
+ }
+ else{
+ sta_gw[0] = sta_ip[0];
+ sta_gw[1] = sta_ip[1];
+ sta_gw[2] = sta_ip[2];
+ sta_gw[3] = 1;
+ }
+
+ if(argv[3] != NULL){
+ ip_addr = inet_addr(argv[3]);
+ sta_netmask[0] = (unsigned char) ip_addr & 0xff;
+ sta_netmask[1] = (unsigned char) (ip_addr >> 8) & 0xff;
+ sta_netmask[2] = (unsigned char) (ip_addr >> 16) & 0xff;
+ sta_netmask[3] = (unsigned char) (ip_addr >> 24) & 0xff;
+ }
+ else{
+ sta_netmask[0] = 255;
+ sta_netmask[1] = 255;
+ sta_netmask[2] = 255;
+ sta_netmask[3] = 0;
+ }
+
+exit:
+ if(error_no==0)
+ at_printf("\r\n[ATPE] OK");
+ else
+ at_printf("\r\n[ATPE] ERROR:%d",error_no);
+
+ return;
+
+}
+#endif
+
+#elif ATCMD_VER == ATVER_2 // UART module at command
+
+//ATPA=,,,[,]
+void fATPA(void *arg)
+{
+ int argc, error_no = 0;
+ char *argv[MAX_ARGC] = {0};
+
+#if CONFIG_LWIP_LAYER
+ struct ip_addr ipaddr;
+ struct ip_addr netmask;
+ struct ip_addr gw;
+ struct netif * pnetif;
+#endif
+ int timeout = 20;
+ unsigned char hidden_ssid = 0;
+ rtw_mode_t wifi_mode_copy;
+
+ if(!arg){
+ AT_DBG_MSG(AT_FLAG_WIFI, AT_DBG_ERROR,
+ "\r\n[ATPA] Usage: ATPA=,,,[,]");
+ error_no = 1;
+ goto exit;
+ }
+
+ argc = parse_param(arg, argv);
+ if(argc < 5){
+ //at_printf("\r\n[ATPA] ERROR : command format error");
+ error_no = 1;
+ goto exit;
+ }
+
+ if( (wifi_mode!=RTW_MODE_AP) && (wifi_mode!=RTW_MODE_STA_AP) ){
+ //at_printf("\r\n[ATPA] ERROR : wifi mode error");
+ error_no = 5;
+ goto exit;
+ }
+ wifi_mode_copy = wifi_mode;
+
+ //SSID
+ if(argv[1] != NULL){
+ ap.ssid.len = strlen((char*)argv[1]);
+ if(ap.ssid.len > 32){
+ //at_printf("\r\n[ATPA] ERROR : SSID length can't exceed 32");
+ error_no = 2;
+ goto exit;
+ }
+ strcpy((char *)ap.ssid.val, (char*)argv[1]);
+ }
+ else{
+ //at_printf("\r\n[ATPA] ERROR : SSID can't be empty");
+ error_no = 2;
+ goto exit;
+ }
+
+ //PASSWORD
+ if(argv[2] != NULL){
+ if( (strlen(argv[2]) < 8) || (strlen(argv[2]) > 64)){
+ //at_printf("\r\n[ATPA] ERROR : PASSWORD length error");
+ error_no = 2;
+ goto exit;
+ }
+ strcpy((char *)password, (char*)argv[2]);
+ ap.password = password;
+ ap.password_len = strlen((char*)argv[2]);
+ ap.security_type = RTW_SECURITY_WPA2_AES_PSK;
+ }
+ else{
+ ap.security_type = RTW_SECURITY_OPEN;
+ }
+
+ //CHANNEL
+ if(argv[3] != NULL){
+ ap.channel = (unsigned char) atoi((const char *)argv[3]);
+ if( (ap.channel < 0) || (ap.channel > 11) ){
+ //at_printf("\r\n[ATPA] ERROR : channel number error");
+ error_no = 2;
+ goto exit;
+ }
+ }
+
+ //HIDDEN SSID
+ if(argv[4] != NULL){
+ if( (atoi(argv[4]) != 0) && (atoi(argv[4]) != 1)){
+ //at_printf("\r\n[ATPA] ERROR : HIDDEN SSID must be 0 or 1");
+ error_no = 2;
+ goto exit;
+ }
+ hidden_ssid = (unsigned char) atoi((const char *)argv[4]);
+ }
+
+ //MAX NUMBER OF STATION
+ if(argv[5] != NULL){
+ unsigned char max_sta = atoi(argv[5]);
+ if(wext_set_sta_num(max_sta) != 0){
+ error_no = 2;
+ goto exit;
+ }
+ }
+
+#if CONFIG_WEBSERVER
+ //store into flash
+ memset(wifi_setting.ssid, 0, sizeof(wifi_setting.ssid));
+ memcpy(wifi_setting.ssid, ap.ssid.val, strlen((char*)ap.ssid.val));
+ wifi_setting.ssid[ap.ssid.len] = '\0';
+ wifi_setting.security_type = ap.security_type;
+ if(ap.security_type !=0)
+ wifi_setting.security_type = 1;
+ else
+ wifi_setting.security_type = 0;
+ if (ap.password)
+ memcpy(wifi_setting.password, ap.password, strlen((char*)ap.password));
+ else
+ memset(wifi_setting.password, 0, sizeof(wifi_setting.password));
+ wifi_setting.channel = ap.channel;
+#if CONFIG_READ_FLASH
+ StoreApInfo();
+#endif
+#endif
+
+#if CONFIG_LWIP_LAYER
+ dhcps_deinit();
+#endif
+
+ wifi_unreg_event_handler(WIFI_EVENT_DISCONNECT, atcmd_wifi_disconn_hdl);
+
+ wifi_off();
+ vTaskDelay(20);
+
+ if (wifi_on(wifi_mode_copy) < 0){
+ //at_printf("\r\n[ATPA] ERROR : Wifi on failed");
+ error_no = 3;
+ goto exit;
+ }
+
+ if(wifi_start_ap((char*)ap.ssid.val, ap.security_type, (char*)ap.password, ap.channel, hidden_ssid) < 0) {
+ //at_printf("\r\n[ATPA] ERROR : Start AP failed");
+ error_no = 4;
+ goto exit;
+ }
+
+ while(1) {
+ char essid[33];
+ if(wifi_mode_copy == RTW_MODE_AP ){
+ if(wext_get_ssid( WLAN0_NAME , (unsigned char *) essid) > 0) {
+ if(strcmp((const char *) essid, (const char *)ap.ssid.val) == 0) {
+ break;
+ }
+ }
+ }
+ else if(wifi_mode_copy == RTW_MODE_STA_AP ){
+ if(wext_get_ssid( WLAN1_NAME , (unsigned char *) essid) > 0) {
+ if(strcmp((const char *) essid, (const char *)ap.ssid.val) == 0) {
+ break;
+ }
+ }
+ }
+
+ if(timeout == 0) {
+ //at_printf("\r\n[ATPA] ERROR : Start AP timeout");
+ error_no = 4;
+ break;
+ }
+
+ vTaskDelay(1 * configTICK_RATE_HZ);
+ timeout --;
+ }
+#if CONFIG_LWIP_LAYER
+ if(wifi_mode == RTW_MODE_STA_AP)
+ pnetif = &xnetif[1];
+ else
+ pnetif = &xnetif[0];
+
+ LwIP_UseStaticIP(pnetif);
+
+ if(dhcp_mode_ap == 1)
+ dhcps_init(pnetif);
+#endif
+
+exit:
+ init_wifi_struct();
+
+ if(error_no == 0)
+ at_printf("\r\n[ATPA] OK");
+ else
+ at_printf("\r\n[ATPA] ERROR:%d",error_no);
+
+ return;
+}
+
+/*find ap with "ssid" from scan list*/
+static int _find_ap_from_scan_buf(char*buf, int buflen, char *target_ssid, void *user_data)
+{
+ rtw_wifi_setting_t *pwifi = (rtw_wifi_setting_t *)user_data;
+ int plen = 0;
+
+ while(plen < buflen){
+ u8 len, ssid_len, security_mode;
+ char *ssid;
+
+ // len offset = 0
+ len = (int)*(buf + plen);
+ // check end
+ if(len == 0) break;
+ // ssid offset = 14
+ ssid_len = len - 14;
+ ssid = buf + plen + 14 ;
+ if((ssid_len == strlen(target_ssid))
+ && (!memcmp(ssid, target_ssid, ssid_len)))
+ {
+ strcpy((char*)pwifi->ssid, target_ssid);
+ // channel offset = 13
+ pwifi->channel = *(buf + plen + 13);
+ // security_mode offset = 11
+ security_mode = (u8)*(buf + plen + 11);
+ if(security_mode == IW_ENCODE_ALG_NONE)
+ pwifi->security_type = RTW_SECURITY_OPEN;
+ else if(security_mode == IW_ENCODE_ALG_WEP)
+ pwifi->security_type = RTW_SECURITY_WEP_PSK;
+ else if(security_mode == IW_ENCODE_ALG_CCMP)
+ pwifi->security_type = RTW_SECURITY_WPA2_AES_PSK;
+ break;
+ }
+ plen += len;
+ }
+ return 0;
+}
+
+/*get ap security mode from scan list*/
+static int _get_ap_security_mode(IN char * ssid, OUT rtw_security_t *security_mode, OUT u8 * channel)
+{
+ rtw_wifi_setting_t wifi;
+ u32 scan_buflen = 1000;
+
+ memset(&wifi, 0, sizeof(wifi));
+
+ if(wifi_scan_networks_with_ssid(_find_ap_from_scan_buf, (void*)&wifi, scan_buflen, ssid, strlen(ssid)) != RTW_SUCCESS){
+ printf("Wifi scan failed!\n");
+ return 0;
+ }
+
+ if(strcmp(wifi.ssid, ssid) == 0){
+ *security_mode = wifi.security_type;
+ *channel = wifi.channel;
+ return 1;
+ }
+
+ return 0;
+}
+
+//ATPN=,[,,]
+static void atcmd_wifi_disconn_hdl( char* buf, int buf_len, int flags, void* userdata)
+{
+ #if CONFIG_LOG_SERVICE_LOCK
+ log_service_lock();
+ #endif
+ at_printf("\r\n[ATWD] OK");
+ at_printf(STR_END_OF_ATCMD_RET);
+ #if CONFIG_LOG_SERVICE_LOCK
+ log_service_unlock();
+ #endif
+}
+void fATPN(void *arg)
+{
+ int argc, error_no = 0;
+ int i,j;
+ char *argv[MAX_ARGC] = {0};
+
+ int mode, ret;
+ unsigned long tick1 = xTaskGetTickCount();
+ unsigned long tick2, tick3;
+ char empty_bssid[6] = {0}, assoc_by_bssid = 0;
+ u8 connect_channel;
+ u8 pscan_config;
+
+ if(!arg){
+ AT_DBG_MSG(AT_FLAG_WIFI, AT_DBG_ERROR,
+ "\r\n[ATPN] Usage : ATPN=,[,,]");
+ error_no = 1;
+ goto exit;
+ }
+
+ argc = parse_param(arg, argv);
+ if( (argc < 2) || (argc > 5) ){
+ //at_printf("\r\n[ATPN] ERROR : command format error");
+ error_no = 1;
+ goto exit;
+ }
+
+ if( (wifi_mode!=RTW_MODE_STA) && (wifi_mode!=RTW_MODE_STA_AP) ){
+ //at_printf("\r\n[ATPN] ERROR : wifi mode error");
+ error_no = 5;
+ goto exit;
+ }
+
+ //SSID
+ if(argv[1] != NULL){
+ strcpy((char *)wifi.ssid.val, (char*)argv[1]);
+ wifi.ssid.len = strlen((char*)argv[1]);
+ }else{
+ //at_printf("\r\n[ATPN] ERROR : SSID can't be Empty");
+ error_no = 2;
+ goto exit;
+ }
+ wifi.security_type = RTW_SECURITY_OPEN;
+
+ //PASSWORD
+ if(argv[2] != NULL){
+ int pwd_len = strlen(argv[2]);
+ if(pwd_len > 64 || (pwd_len < 8 && pwd_len != 5)){
+ //at_printf("\r\n[ATPN] ERROR : PASSWORD format error");
+ error_no = 2;
+ goto exit;
+ }
+ strcpy((char *)password, (char*)argv[2]);
+ wifi.password = password;
+ wifi.password_len = strlen((char*)argv[2]);
+ wifi.security_type = RTW_SECURITY_WPA2_AES_PSK;
+ }
+
+ //KEYID
+ if(argv[3] != NULL){
+ if((strlen((const char *)argv[3]) != 1 ) || (*(char*)argv[3] <'0' ||*(char*)argv[3] >'3')) {
+ //at_printf("\r\n[ATPN] ERROR : Wrong WEP key id. Must be one of 0,1,2, or 3");
+ error_no = 2;
+ goto exit;
+ }
+ wifi.key_id = atoi((const char *)(argv[3]));
+ wifi.security_type = RTW_SECURITY_WEP_PSK;
+ }
+
+ //BSSID
+ if(argv[4] != NULL){
+ if(strlen(argv[4]) != 12){
+ //at_printf("\r\n[ATPN] ERROR : BSSID format error");
+ error_no = 2;
+ goto exit;
+ }
+ for (i=0, j=0; i= 3){
+ printf("Can't get AP security mode and channel.\n");
+ error_no = 6;
+ goto exit;
+ }
+ }
+ if(wifi.security_type == RTW_SECURITY_WEP_PSK || wifi.security_type == RTW_SECURITY_WEP_SHARED)
+ wifi.key_id = (wifi.key_id <0 || wifi.key_id >3)?0:wifi.key_id;
+ }
+ pscan_config = PSCAN_ENABLE;
+ if(connect_channel > 0 && connect_channel < 14)
+ wifi_set_pscan_chan(&connect_channel, &pscan_config, 1);
+#endif
+
+ wifi_unreg_event_handler(WIFI_EVENT_DISCONNECT, atcmd_wifi_disconn_hdl);
+
+ ret = wifi_connect(
+ wifi.bssid.octet,
+ assoc_by_bssid,
+ (char*)wifi.ssid.val,
+ wifi.security_type,
+ (char*)wifi.password,
+ wifi.key_id,
+ NULL);
+
+ if(ret!= RTW_SUCCESS){
+ //at_printf("\r\n[ATPN] ERROR: Can't connect to AP");
+ error_no = 4;
+ goto exit;
+ }
+
+#if CONFIG_LWIP_LAYER
+ if (dhcp_mode_sta == 2){
+ struct netif * pnetif = &xnetif[0];
+ LwIP_UseStaticIP(pnetif);
+ dhcps_init(pnetif);
+ }
+ else{
+ ret = LwIP_DHCP(0, DHCP_START);
+ if(ret != DHCP_ADDRESS_ASSIGNED)
+ error_no = 7;
+ }
+#endif
+
+
+exit:
+ init_wifi_struct();
+ if(error_no == 0){
+ wifi_reg_event_handler(WIFI_EVENT_DISCONNECT, atcmd_wifi_disconn_hdl, NULL);
+ at_printf("\r\n[ATPN] OK");
+ }
+ else
+ at_printf("\r\n[ATPN] ERROR:%d",error_no);
+
+ return;
+}
+
+//ATPH=,
+void fATPH(void *arg)
+{
+ int argc, error_no = 0;
+ char *argv[MAX_ARGC] = {0};
+ int mode,enable;
+
+ if(!arg){
+ AT_DBG_MSG(AT_FLAG_WIFI, AT_DBG_ERROR,
+ "\r\n[ATPH] Usage : ATPH=,");
+ error_no = 1;
+ goto exit;
+ }
+
+ argc = parse_param(arg, argv);
+ if(argc != 3){
+ //at_printf("\r\n[ATPH] ERROR : command format error");
+ error_no = 1;
+ goto exit;
+ }
+
+ if(argv[1] != NULL){
+ mode = atoi((const char *)(argv[1]));
+ if(mode != 1 && mode != 2){
+ //at_printf("\r\n[ATPH] ERROR : parameter must be 1 or 2");
+ error_no = 2;
+ goto exit;
+ }
+ }
+
+ if(argv[2] != NULL){
+ enable = atoi((const char *)(argv[2]));
+ if(enable != 1 && enable != 2){
+ //at_printf("\r\n[ATPH] ERROR : parameter must be 1 or 2");
+ error_no = 2;
+ goto exit;
+ }
+ if(mode == 1)
+ dhcp_mode_ap = enable;
+ else if(mode == 2)
+ dhcp_mode_sta = enable;
+ }
+
+exit:
+ if(error_no==0)
+ at_printf("\r\n[ATPH] OK");
+ else
+ at_printf("\r\n[ATPH] ERROR:%d",error_no);
+
+ return;
+
+}
+
+//ATPE=(,,)
+void fATPE(void *arg)
+{
+ int argc, error_no = 0;
+ char *argv[MAX_ARGC] = {0};
+ unsigned int ip_addr = 0;
+ //unsigned char sta_ip[4] = {192,168,3,80}, sta_netmask[4] = {255,255,255,0}, sta_gw[4] = {192,168,3,1};
+
+ if(!arg){
+ AT_DBG_MSG(AT_FLAG_WIFI, AT_DBG_ERROR,
+ "\r\n[ATPE] Usage : ATPE=(,,)");
+ error_no = 1;
+ goto exit;
+ }
+
+ argc = parse_param(arg, argv);
+ if( (argc > 4) || (argc < 2) ){
+ //at_printf("\r\n[ATPE] ERROR : command format error");
+ error_no = 1;
+ goto exit;
+ }
+
+ if(argv[1] != NULL){
+ ip_addr = inet_addr(argv[1]);
+ sta_ip[0] = (unsigned char) ip_addr & 0xff;
+ sta_ip[1] = (unsigned char) (ip_addr >> 8) & 0xff;
+ sta_ip[2] = (unsigned char) (ip_addr >> 16) & 0xff;
+ sta_ip[3] = (unsigned char) (ip_addr >> 24) & 0xff;
+ }
+ else{
+ //at_printf("\r\n[ATPE] ERROR : parameter format error");
+ error_no = 2;
+ goto exit;
+ }
+
+ if(argv[2] != NULL){
+ ip_addr = inet_addr(argv[2]);
+ sta_gw[0] = (unsigned char) ip_addr & 0xff;
+ sta_gw[1] = (unsigned char) (ip_addr >> 8) & 0xff;
+ sta_gw[2] = (unsigned char) (ip_addr >> 16) & 0xff;
+ sta_gw[3] = (unsigned char) (ip_addr >> 24) & 0xff;
+ }
+ else{
+ sta_gw[0] = sta_ip[0];
+ sta_gw[1] = sta_ip[1];
+ sta_gw[2] = sta_ip[2];
+ sta_gw[3] = 1;
+ }
+
+ if(argv[3] != NULL){
+ ip_addr = inet_addr(argv[3]);
+ sta_netmask[0] = (unsigned char) ip_addr & 0xff;
+ sta_netmask[1] = (unsigned char) (ip_addr >> 8) & 0xff;
+ sta_netmask[2] = (unsigned char) (ip_addr >> 16) & 0xff;
+ sta_netmask[3] = (unsigned char) (ip_addr >> 24) & 0xff;
+ }
+ else{
+ sta_netmask[0] = 255;
+ sta_netmask[1] = 255;
+ sta_netmask[2] = 255;
+ sta_netmask[3] = 0;
+ }
+
+exit:
+ if(error_no==0)
+ at_printf("\r\n[ATPE] OK");
+ else
+ at_printf("\r\n[ATPE] ERROR:%d",error_no);
+
+ return;
+
+}
+
+//ATPF=,,
+void fATPF(void *arg)
+{
+ int argc, error_no = 0;
+ char *argv[MAX_ARGC] = {0};
+ unsigned int ip_addr = 0;
+ struct ip_addr start_ip, end_ip;
+
+ if(!arg){
+ AT_DBG_MSG(AT_FLAG_WIFI, AT_DBG_ERROR,
+ "\r\n[ATPF] Usage : ATPF=,,(,,)");
+ error_no = 1;
+ goto exit;
+ }
+
+ argc = parse_param(arg, argv);
+ if( (argc != 4) ){
+ //at_printf("\r\n[ATPF] ERROR : command format error");
+ error_no = 1;
+ goto exit;
+ }
+
+ if(argv[1] != NULL){
+ start_ip.addr = inet_addr(argv[1]);
+ }
+ else{
+ //at_printf("\r\n[ATPF] ERROR : parameter format error");
+ error_no = 2;
+ goto exit;
+ }
+
+ if(argv[2] != NULL){
+ end_ip.addr = inet_addr(argv[2]);
+ }
+ else{
+ //at_printf("\r\n[ATPF] ERROR : parameter format error");
+ error_no = 2;
+ goto exit;
+ }
+
+ dhcps_set_addr_pool(1,&start_ip,&end_ip);
+
+ if(argv[3] != NULL){
+ ip_addr = inet_addr(argv[3]);
+ ap_ip[0] = (unsigned char) ip_addr & 0xff;
+ ap_ip[1] = (unsigned char) (ip_addr >> 8) & 0xff;
+ ap_ip[2] = (unsigned char) (ip_addr >> 16) & 0xff;
+ ap_ip[3] = (unsigned char) (ip_addr >> 24) & 0xff;
+ }
+ else{
+ //at_printf("\r\n[ATPF] ERROR : parameter format error");
+ error_no = 2;
+ goto exit;
+ }
+
+ ap_gw[0] = ap_ip[0];
+ ap_gw[1] = ap_ip[1];
+ ap_gw[2] = ap_ip[2];
+ ap_gw[3] = ap_ip[3];
+
+ ap_netmask[0] = 255;
+ ap_netmask[1] = 255;
+ ap_netmask[2] = 255;
+ ap_netmask[3] = 0;
+
+exit:
+ if(error_no==0)
+ at_printf("\r\n[ATPF] OK");
+ else
+ at_printf("\r\n[ATPF] ERROR:%d",error_no);
+
+ return;
+}
+
+int atcmd_wifi_read_info_from_flash(u8 *read_data, u32 read_len)
+{
+ atcmd_update_partition_info(AT_PARTITION_WIFI, AT_PARTITION_READ, read_data, read_len);
+ return 0;
+}
+
+void atcmd_wifi_write_info_to_flash(rtw_wifi_setting_t *setting, int enable)
+{
+ struct atcmd_wifi_conf *data_to_flash;
+ rtw_wifi_setting_t *old_setting;
+
+ flash_t flash;
+ u32 channel = 0, i, write_needed = 0;
+ u8 index = 0;
+ u32 data;
+
+ data_to_flash = (struct atcmd_wifi_conf *)malloc(sizeof(struct atcmd_wifi_conf));
+
+ if(data_to_flash) {
+ if(enable){
+ memset((u8 *)data_to_flash, 0, sizeof(struct atcmd_wifi_conf));
+ atcmd_update_partition_info(AT_PARTITION_WIFI, AT_PARTITION_READ, (u8 *)data_to_flash, sizeof(struct atcmd_wifi_conf));
+ old_setting = &(data_to_flash->setting);
+ if(memcmp((u8 *)old_setting, setting, sizeof(rtw_wifi_setting_t))){
+ memcpy(old_setting, setting, sizeof(rtw_wifi_setting_t));
+ write_needed = 1;
+ }
+ if(setting->mode == RTW_MODE_STA || setting->mode == RTW_MODE_STA_AP){
+ struct wlan_fast_reconnect reconn;
+ int found = 0;
+ /*clean wifi ssid,key and bssid*/
+ memset((u8 *)&reconn, 0, sizeof(struct wlan_fast_reconnect));
+
+ channel = setting->channel;
+
+ memset(psk_essid[index], 0, sizeof(psk_essid[index]));
+ strncpy(psk_essid[index], setting->ssid, strlen(setting->ssid));
+ switch(setting->security_type){
+ case RTW_SECURITY_OPEN:
+ memset(psk_passphrase[index], 0, sizeof(psk_passphrase[index]));
+ memset(wpa_global_PSK[index], 0, sizeof(wpa_global_PSK[index]));
+ reconn.security_type = RTW_SECURITY_OPEN;
+ break;
+ case RTW_SECURITY_WEP_PSK:
+ channel |= (setting->key_idx) << 28;
+ memset(psk_passphrase[index], 0, sizeof(psk_passphrase[index]));
+ memset(wpa_global_PSK[index], 0, sizeof(wpa_global_PSK[index]));
+ memcpy(psk_passphrase[index], setting->password, sizeof(psk_passphrase[index]));
+ reconn.security_type = RTW_SECURITY_WEP_PSK;
+ break;
+ case RTW_SECURITY_WPA_TKIP_PSK:
+ reconn.security_type = RTW_SECURITY_WPA_TKIP_PSK;
+ break;
+ case RTW_SECURITY_WPA2_AES_PSK:
+ reconn.security_type = RTW_SECURITY_WPA2_AES_PSK;
+ break;
+ default:
+ break;
+ }
+
+ memcpy(reconn.psk_essid, psk_essid[index], sizeof(reconn.psk_essid));
+ if (strlen(psk_passphrase64) == 64) {
+ memcpy(reconn.psk_passphrase, psk_passphrase64, sizeof(reconn.psk_passphrase));
+ } else {
+ memcpy(reconn.psk_passphrase, psk_passphrase[index], sizeof(reconn.psk_passphrase));
+ }
+ memcpy(reconn.wpa_global_PSK, wpa_global_PSK[index], sizeof(reconn.wpa_global_PSK));
+ memcpy(&(reconn.channel), &channel, 4);
+
+ if(data_to_flash->reconn_num < 0 || data_to_flash->reconn_num > ATCMD_WIFI_CONN_STORE_MAX_NUM ||
+ data_to_flash->reconn_last_index < 0 || data_to_flash->reconn_last_index > ATCMD_WIFI_CONN_STORE_MAX_NUM
+ ){
+ data_to_flash->reconn_num = 0;
+ data_to_flash->reconn_last_index = -1;
+ }
+
+ reconn.enable = enable;
+ for(i = 0; i < data_to_flash->reconn_num; i++){
+ if(memcmp((u8 *)&reconn, (u8 *)&(data_to_flash->reconn[i]), sizeof(struct wlan_fast_reconnect)) == 0) {
+ AT_DBG_MSG(AT_FLAG_WIFI, AT_DBG_ALWAYS,
+ "the same profile found in flash");
+ found = 1;
+ break;
+ }
+ }
+ if(!found){
+ data_to_flash->reconn_last_index++;
+ if(data_to_flash->reconn_last_index >= ATCMD_WIFI_CONN_STORE_MAX_NUM)
+ data_to_flash->reconn_last_index -= ATCMD_WIFI_CONN_STORE_MAX_NUM;
+ memcpy((u8 *)&data_to_flash->reconn[data_to_flash->reconn_last_index], (u8 *)&reconn, sizeof(struct wlan_fast_reconnect));
+ data_to_flash->reconn_num++;
+ if(data_to_flash->reconn_num > ATCMD_WIFI_CONN_STORE_MAX_NUM)
+ data_to_flash->reconn_num = ATCMD_WIFI_CONN_STORE_MAX_NUM;
+ write_needed = 1;
+ }
+ }
+ if(write_needed || data_to_flash->auto_enable != enable){
+ data_to_flash->auto_enable = enable;
+ atcmd_update_partition_info(AT_PARTITION_WIFI, AT_PARTITION_WRITE, (u8 *)data_to_flash, sizeof(struct atcmd_wifi_conf));
+ }
+ }else{
+ atcmd_update_partition_info(AT_PARTITION_WIFI, AT_PARTITION_ERASE, (u8 *)data_to_flash, sizeof(struct atcmd_wifi_conf));
+ }
+ }
+ if(data_to_flash) {
+ free(data_to_flash);
+ }
+}
+
+int atcmd_wifi_restore_from_flash(void)
+{
+ flash_t flash;
+ struct atcmd_wifi_conf *data;
+ rtw_wifi_setting_t *setting;
+ struct wlan_fast_reconnect *reconn;
+ uint32_t channel;
+ uint32_t security_type;
+ uint8_t pscan_config;
+ char key_id[2] = {0};
+ int ret = -1, i;
+ int mode;
+ rtw_network_info_t wifi = {
+ {0}, // ssid
+ {0}, // bssid
+ 0, // security
+ NULL, // password
+ 0, // password len
+ -1 // key id
+ };
+
+ data = (struct atcmd_wifi_conf *)rtw_zmalloc(sizeof(struct atcmd_wifi_conf));
+ if(data){
+ atcmd_update_partition_info(AT_PARTITION_WIFI, AT_PARTITION_READ, (u8 *)data, sizeof(struct atcmd_wifi_conf));
+ if(data->auto_enable != 1)
+ goto exit;
+ setting = &data->setting;
+ if(setting->mode == RTW_MODE_AP || setting->mode == RTW_MODE_STA_AP){
+ //start AP here
+ goto exit;
+ }
+
+ //Check if in AP mode
+ wext_get_mode(WLAN0_NAME, &mode);
+ if(mode == IW_MODE_MASTER) {
+#if CONFIG_LWIP_LAYER
+ dhcps_deinit();
+#endif
+ wifi_off();
+ vTaskDelay(20);
+ if (wifi_on(RTW_MODE_STA) < 0){
+ printf("\n\rERROR: Wifi on failed!");
+ ret = -1;
+ goto exit;
+ }
+ }
+
+#if CONFIG_AUTO_RECONNECT
+ //setup reconnection flag
+ wifi_set_autoreconnect(0);
+#endif
+ int last_index = data->reconn_last_index;
+ for(i = 0; i < data->reconn_num; i++){
+ reconn = &data->reconn[last_index];
+ last_index ++;
+ if(last_index >= ATCMD_WIFI_CONN_STORE_MAX_NUM)
+ last_index -= ATCMD_WIFI_CONN_STORE_MAX_NUM;
+ if(reconn->enable != 1){
+ continue;
+ }
+ memcpy(psk_essid, reconn->psk_essid, sizeof(reconn->psk_essid));
+ memcpy(psk_passphrase, reconn->psk_passphrase, sizeof(reconn->psk_passphrase));
+ memcpy(wpa_global_PSK, reconn->wpa_global_PSK, sizeof(reconn->wpa_global_PSK));
+ channel = reconn->channel;
+ sprintf(key_id,"%d",(char) (channel>>28));
+ channel &= 0xff;
+ security_type = reconn->security_type;
+ pscan_config = PSCAN_ENABLE | PSCAN_FAST_SURVEY;
+ //set partial scan for entering to listen beacon quickly
+ wifi_set_pscan_chan((uint8_t *)&channel, &pscan_config, 1);
+
+ wifi.security_type = security_type;
+ //SSID
+ strcpy((char *)wifi.ssid.val, (char*)psk_essid);
+ wifi.ssid.len = strlen((char*)psk_essid);
+
+ switch(security_type){
+ case RTW_SECURITY_WEP_PSK:
+ wifi.password = (unsigned char*) psk_passphrase;
+ wifi.password_len = strlen((char*)psk_passphrase);
+ wifi.key_id = atoi((const char *)key_id);
+ break;
+ case RTW_SECURITY_WPA_TKIP_PSK:
+ case RTW_SECURITY_WPA2_AES_PSK:
+ wifi.password = (unsigned char*) psk_passphrase;
+ wifi.password_len = strlen((char*)psk_passphrase);
+ break;
+ default:
+ break;
+ }
+ ret = wifi_connect(
+ NULL,
+ 0,
+ (char*)wifi.ssid.val,
+ wifi.security_type,
+ (char*)wifi.password,
+ wifi.key_id,
+ NULL);
+ if(ret == RTW_SUCCESS){
+ LwIP_DHCP(0, DHCP_START);
+ ret = 0;
+ break;
+ }
+ }
+ }
+
+exit:
+ if(ret == 0)
+ wifi_reg_event_handler(WIFI_EVENT_DISCONNECT, atcmd_wifi_disconn_hdl, NULL);
+ if(data)
+ rtw_mfree((u8 *)data, sizeof(struct wlan_fast_reconnect));
+ return ret;
+}
+
+//ATPG=
+void fATPG(void *arg)
+{
+ int argc, error_no = 0;
+ char *argv[MAX_ARGC] = {0};
+// flash_t flash;
+// struct wlan_fast_reconnect read_data = {0};
+
+ if(!arg){
+ AT_DBG_MSG(AT_FLAG_WIFI, AT_DBG_ERROR,
+ "\r\n[ATPG] Usage : ATPG=");
+ error_no = 1;
+ goto exit;
+ }
+ argc = parse_param(arg, argv);
+ if(argc != 2){
+ //at_printf("\r\n[ATPG] ERROR : command format error");
+ error_no = 1;
+ goto exit;
+ }
+
+ //ENABLE FAST CONNECT
+ if(argv[1] != NULL){
+#if 0
+ device_mutex_lock(RT_DEV_LOCK_FLASH);
+ flash_stream_read(&flash, FAST_RECONNECT_DATA, sizeof(struct wlan_fast_reconnect), (u8 *) &read_data);
+ read_data.enable = atoi((const char *)(argv[1]));
+ if(read_data.enable != 0 && read_data.enable != 1){
+ //at_printf("\r\n[ATPG] ERROR : parameter must be 0 or 1");
+ error_no = 2;
+ device_mutex_unlock(RT_DEV_LOCK_FLASH);
+ goto exit;
+ }
+ flash_erase_sector(&flash, FAST_RECONNECT_DATA);
+ flash_stream_write(&flash, FAST_RECONNECT_DATA, sizeof(struct wlan_fast_reconnect), (u8 *) &read_data);
+ device_mutex_unlock(RT_DEV_LOCK_FLASH);
+#else
+ rtw_wifi_setting_t setting;
+ int enable = atoi((const char *)(argv[1]));
+ if(enable != 0 && enable != 1){
+ error_no = 2;
+ goto exit;
+ }
+ if(enable == 1){
+ u8 *ifname[1] = {WLAN0_NAME};
+ if(wifi_get_setting((const char*)ifname[0],&setting)){
+ AT_DBG_MSG(AT_FLAG_WIFI, AT_DBG_ERROR,
+ "wifi_get_setting fail");
+ error_no = 3;
+ goto exit;
+ }
+ }
+ atcmd_wifi_write_info_to_flash(&setting, enable);
+#endif
+ }
+
+exit:
+ if(error_no==0)
+ at_printf("\r\n[ATPG] OK");
+ else
+ at_printf("\r\n[ATPG] ERROR:%d",error_no);
+
+ return;
+}
+
+//ATPM=
+void fATPM(void *arg)
+{
+ int argc, error_no = 0;
+ char *argv[MAX_ARGC] = {0};
+
+ if(!arg){
+ AT_DBG_MSG(AT_FLAG_WIFI, AT_DBG_ERROR,
+ "\r\n[ATPM] Usage : ATPM=");
+ error_no = 1;
+ goto exit;
+ }
+
+ argc = parse_param(arg, argv);
+ if(argc != 2){
+ //at_printf("\r\n[ATPM] ERROR : command format error");
+ error_no = 1;
+ goto exit;
+ }
+
+ if(argv[1] != NULL){
+ if(strlen(argv[1]) != 12){
+ //at_printf("\r\n[ATPM] ERROR : BSSID format error");
+ error_no = 2;
+ goto exit;
+ }
+ wifi_set_mac_address(argv[1]);
+ }
+
+exit:
+ if(error_no==0)
+ at_printf("\r\n[ATPM] OK");
+ else
+ at_printf("\r\n[ATPM] ERROR:%d",error_no);
+
+ return;
+
+}
+
+//ATPW=
+void fATPW(void *arg)
+{
+ int argc, error_no = 0;
+ char *argv[MAX_ARGC] = {0};
+
+ if(!arg){
+ AT_DBG_MSG(AT_FLAG_WIFI, AT_DBG_ERROR,
+ "\r\n[ATPW] Usage : ATPW=");
+ error_no = 1;
+ goto exit;
+ }
+
+ argc = parse_param(arg, argv);
+ if(argc != 2){
+ //at_printf("\r\n[ATPW] ERROR : command format error");
+ error_no = 1;
+ goto exit;
+ }
+
+ if(argv[1] != NULL){
+ wifi_mode = atoi((const char *)(argv[1]));
+ if((wifi_mode!=RTW_MODE_STA) && (wifi_mode!=RTW_MODE_AP) && (wifi_mode!=RTW_MODE_STA_AP) ){
+ //at_printf("\r\n[ATPW] ERROR : parameter must be 1 , 2 or 3");
+ error_no = 2;
+ }
+ }
+
+exit:
+ if(error_no==0)
+ at_printf("\r\n[ATPW] OK");
+ else
+ at_printf("\r\n[ATPW] ERROR:%d",error_no);
+
+ return;
+}
+
+void print_wlan_help(void *arg){
+ at_printf("\r\nWLAN AT COMMAND SET:");
+ at_printf("\r\n==============================");
+ at_printf("\r\n1. Wlan Scan for Network Access Point");
+ at_printf("\r\n # ATWS");
+ at_printf("\r\n2. Connect to an AES AP");
+ at_printf("\r\n # ATPN=,,(,)");
+ at_printf("\r\n3. Create an AES AP");
+ at_printf("\r\n # ATPA=,,,");
+}
+
+#endif // end of #if ATCMD_VER == ATVER_1
+
+#endif // end of #if CONFIG_WLAN
+
+#if CONFIG_LWIP_LAYER
+#if ATCMD_VER == ATVER_1
+void fATWL(void *arg){
+#if CONFIG_SSL_CLIENT
+ int argc;
+ char *argv[MAX_ARGC] = {0};
+ printf("[ATWL]: _AT_WLAN_SSL_CLIENT_\n\r");
+ argv[0] = "ssl_client";
+ if(!arg){
+ printf("ATWL=SSL_SERVER_HOST\n\r");
+ return;
+ }
+ if((argc = parse_param(arg, argv)) > 1){
+ if(argc != 2) {
+ printf("ATWL=SSL_SERVER_HOST\n\r");
+ return;
+ }
+
+ cmd_ssl_client(argc, argv);
+ }
+#else
+ printf("Please set CONFIG_SSL_CLIENT 1 in platform_opts.h to enable ATWL command\n");
+#endif
+}
+
+void fATWI(void *arg){
+ int argc;
+ char *argv[MAX_ARGC] = {0};
+
+ printf("[ATWI]: _AT_WLAN_PING_TEST_\n\r");
+
+ if(!arg){
+ printf("\n\r[ATWI] Usage: ATWI=[host],[options]\n");
+ printf("\n\r -t Ping the specified host until stopped\n");
+ printf(" \r -n # Number of echo requests to send (default 4 times)\n");
+ printf(" \r -l # Send buffer size (default 32 bytes)\n");
+ printf("\n\r Example:\n");
+ printf(" \r ATWI=192.168.1.2,-n,100,-l,5000\n");
+ return;
+ }
+
+ argv[0] = "ping";
+
+ if((argc = parse_param(arg, argv)) > 1){
+ cmd_ping(argc, argv);
+ }
+}
+
+void fATWT(void *arg)
+{
+#if CONFIG_BSD_TCP
+ int argc;
+ char *argv[MAX_ARGC] = {0};
+
+ printf("[ATWT]: _AT_WLAN_TCP_TEST_\n\r");
+
+ if(!arg){
+ printf("\n\r[ATWT] Usage: ATWT=[-s|-c,host|stop],[options]\n");
+ printf("\n\r Client/Server:\n");
+ printf(" \r stop terminate client & server\n");
+ printf(" \r -i # seconds between periodic bandwidth reports\n");
+ printf(" \r -l # length of buffer to read or write (default 1460 Bytes)\n");
+ printf(" \r -p # server port to listen on/connect to (default 5001)\n");
+ printf("\n\r Server specific:\n");
+ printf(" \r -s run in server mode\n");
+ printf("\n\r Client specific:\n");
+ printf(" \r -c run in client mode, connecting to \n");
+ printf(" \r -d do a bidirectional test simultaneously\n");
+ printf(" \r -t # time in seconds to transmit for (default 10 secs)\n");
+ printf(" \r -n #[KM] number of bytes to transmit (instead of -t)\n");
+ printf("\n\r Example:\n");
+ printf(" \r ATWT=-s,-p,5002\n");
+ printf(" \r ATWT=-c,192.168.1.2,-t,100,-p,5002\n");
+ return;
+ }
+
+ argv[0] = "tcp";
+
+ if((argc = parse_param(arg, argv)) > 1){
+ cmd_tcp(argc, argv);
+ }
+#else
+ printf("Please set CONFIG_BSD_TCP 1 in platform_opts.h to enable ATWT command\n");
+#endif
+}
+
+void fATWU(void *arg)
+{
+#if CONFIG_BSD_TCP
+ int argc;
+ char *argv[MAX_ARGC] = {0};
+
+ printf("[ATWU]: _AT_WLAN_UDP_TEST_\n\r");
+
+ if(!arg){
+ printf("\n\r[ATWU] Usage: ATWU=[-s|-c,host|stop][options]\n");
+ printf("\n\r Client/Server:\n");
+ printf(" \r stop terminate client & server\n");
+ printf(" \r -i # seconds between periodic bandwidth reports\n");
+ printf(" \r -l # length of buffer to read or write (default 1460 Bytes)\n");
+ printf(" \r -p # server port to listen on/connect to (default 5001)\n");
+ printf("\n\r Server specific:\n");
+ printf(" \r -s run in server mode\n");
+ printf("\n\r Client specific:\n");
+ printf(" \r -b #[KM] for UDP, bandwidth to send at in bits/sec (default 1 Mbit/sec)\n");
+ printf(" \r -c run in client mode, connecting to \n");
+ printf(" \r -d do a bidirectional test simultaneously\n");
+ printf(" \r -t # time in seconds to transmit for (default 10 secs)\n");
+ printf(" \r -n #[KM] number of bytes to transmit (instead of -t)\n");
+ printf(" \r -S # set the IP 'type of service'\n");
+ printf("\n\r Example:\n");
+ printf(" \r ATWU=-s,-p,5002\n");
+ printf(" \r ATWU=-c,192.168.1.2,-t,100,-p,5002\n");
+ return;
+ }
+
+ argv[0] = "udp";
+
+ if((argc = parse_param(arg, argv)) > 1){
+ cmd_udp(argc, argv);
+ }
+#else
+ printf("Please set CONFIG_BSD_TCP 1 in platform_opts.h to enable ATWU command\n");
+#endif
+}
+#elif ATCMD_VER == ATVER_2 // uart at command
+//move to atcmd_lwip.c
+#endif
+#endif
+log_item_t at_wifi_items[ ] = {
+#if ATCMD_VER == ATVER_1
+#if CONFIG_LWIP_LAYER
+ {"ATWL", fATWL,},
+ {"ATWI", fATWI,},
+ {"ATWT", fATWT,},
+ {"ATWU", fATWU,},
+#endif
+#if WIFI_LOGO_CERTIFICATION_CONFIG
+ {"ATPE", fATPE,}, // set static IP for STA
+#endif
+#if CONFIG_WLAN
+ {"ATW0", fATW0,},
+ {"ATW1", fATW1,},
+ {"ATW2", fATW2,},
+ {"ATW3", fATW3,},
+ {"ATW4", fATW4,},
+ {"ATW5", fATW5,},
+ {"ATW6", fATW6,},
+ {"ATWA", fATWA,},
+#ifdef CONFIG_CONCURRENT_MODE
+ {"ATWB", fATWB,},
+#endif
+ {"ATWC", fATWC,},
+ {"ATWD", fATWD,},
+ {"ATWP", fATWP,},
+#if CONFIG_WOWLAN_SERVICE
+ {"ATWV", fATWV,},
+#endif
+ {"ATWR", fATWR,},
+ {"ATWS", fATWS,},
+#if SCAN_WITH_SSID
+ {"ATWs", fATWs,},
+#endif
+#ifdef CONFIG_PROMISC
+ {"ATWM", fATWM,},
+#endif
+ {"ATWZ", fATWZ,},
+#if CONFIG_OTA_UPDATE
+ {"ATWO", fATWO,},
+#endif
+#if CONFIG_WEBSERVER
+ {"ATWE", fATWE,},
+#endif
+#if (CONFIG_INCLUDE_SIMPLE_CONFIG)
+ {"ATWQ", fATWQ,},
+#endif
+#ifdef CONFIG_WPS
+ {"ATWW", fATWW,},
+ {"ATWw", fATWw,}, //wps registrar for softap
+#if CONFIG_ENABLE_P2P
+ {"ATWG", fATWG,}, //p2p start
+ {"ATWH", fATWH,}, //p2p stop
+ {"ATWJ", fATWJ,}, //p2p connect
+ {"ATWK", fATWK,}, //p2p disconnect
+ {"ATWN", fATWN,}, //p2p info
+ {"ATWF", fATWF,}, //p2p find
+ {"ATWg", fATWg,}, //p2p auto go start
+#endif
+#endif
+
+#if CONFIG_AIRKISS
+ {"ATWX", fATWX,},
+#endif
+ {"ATW?", fATWx,},
+ {"ATW+ABC", fATWx,},
+#ifdef CONFIG_POWER_SAVING
+ {"ATXP", fATXP,},
+#endif
+#endif
+#elif ATCMD_VER == ATVER_2 // uart at command
+#if CONFIG_WLAN
+ {"ATPA", fATPA,}, // set AP
+ {"ATPN", fATPN,}, // connect to Network
+ {"ATPH", fATPH,}, // set DHCP mode
+ {"ATPE", fATPE,}, // set static IP for STA
+ {"ATPF", fATPF,}, // set DHCP rule for AP
+ {"ATPG", fATPG,}, // set auto connect
+ {"ATPM", fATPM,}, // set MAC address
+ {"ATPW", fATPW,}, // set Wifi mode
+ {"ATWD", fATWD,}, // WiFi Disconnect
+ {"ATWS", fATWS,}, // WiFi scan
+ {"ATW?", fATWx,}, // Wlan Info
+#if (CONFIG_INCLUDE_SIMPLE_CONFIG)
+ {"ATWQ", fATWQ,}, // WiFi simple config
+#endif // #if (CONFIG_INCLUDE_SIMPLE_CONFIG)
+#endif // #if CONFIG_WLAN
+#endif // end of #if ATCMD_VER == ATVER_1
+};
+
+#if ATCMD_VER == ATVER_2
+void print_wifi_at(void *arg){
+ int index;
+ int cmd_len = 0;
+
+ cmd_len = sizeof(at_wifi_items)/sizeof(at_wifi_items[0]);
+ for(index = 0; index < cmd_len; index++)
+ at_printf("\r\n%s", at_wifi_items[index].log_cmd);
+}
+#endif
+
+void at_wifi_init(void)
+{
+#if CONFIG_WLAN
+ init_wifi_struct();
+#endif
+ log_service_add_table(at_wifi_items, sizeof(at_wifi_items)/sizeof(at_wifi_items[0]));
+}
+
+#if SUPPORT_LOG_SERVICE
+log_module_init(at_wifi_init);
+#endif
diff --git a/RTLGDB/USDK/component/common/api/at_cmd/atcmd_wifi.h b/RTLGDB/USDK/component/common/api/at_cmd/atcmd_wifi.h
new file mode 100644
index 0000000..d56ad52
--- /dev/null
+++ b/RTLGDB/USDK/component/common/api/at_cmd/atcmd_wifi.h
@@ -0,0 +1,166 @@
+#ifndef __ATCMD_WIFI_H__
+#define __ATCMD_WIFI_H__
+#include
+#include "main.h"
+#include "lwip_netconf.h"
+#ifdef USE_FLASH_EEP
+#include "flash_eep.h"
+#include "feep_config.h"
+#endif
+
+#ifndef WLAN0_NAME
+ #define WLAN0_NAME "wlan0"
+#endif
+#ifndef WLAN1_NAME
+ #define WLAN1_NAME "wlan1"
+#endif
+/* Give default value if not defined */
+#ifndef NET_IF_NUM
+ #ifdef CONFIG_CONCURRENT_MODE
+ #define NET_IF_NUM ((CONFIG_ETHERNET) + (CONFIG_WLAN) + 1)
+ #else
+ #define NET_IF_NUM ((CONFIG_ETHERNET) + (CONFIG_WLAN))
+ #endif // end of CONFIG_CONCURRENT_MODE
+#endif // end of NET_IF_NUM
+
+/*Static IP ADDRESS*/
+#ifndef IP_ADDR0
+#define IP_ADDR0 192
+#define IP_ADDR1 168
+#define IP_ADDR2 3
+#define IP_ADDR3 80
+#endif
+
+/*NETMASK*/
+#ifndef NETMASK_ADDR0
+#define NETMASK_ADDR0 255
+#define NETMASK_ADDR1 255
+#define NETMASK_ADDR2 255
+#define NETMASK_ADDR3 0
+#endif
+
+/*Gateway Address*/
+#ifndef GW_ADDR0
+#define GW_ADDR0 192
+#define GW_ADDR1 168
+#define GW_ADDR2 3
+#define GW_ADDR3 1
+#endif
+
+/*Static IP ADDRESS*/
+#ifndef AP_IP_ADDR0
+#define AP_IP_ADDR0 192
+#define AP_IP_ADDR1 168
+#define AP_IP_ADDR2 43
+#define AP_IP_ADDR3 1
+#endif
+
+/*NETMASK*/
+#ifndef AP_NETMASK_ADDR0
+#define AP_NETMASK_ADDR0 255
+#define AP_NETMASK_ADDR1 255
+#define AP_NETMASK_ADDR2 255
+#define AP_NETMASK_ADDR3 0
+#endif
+
+/*Gateway Address*/
+#ifndef AP_GW_ADDR0
+#define AP_GW_ADDR0 192
+#define AP_GW_ADDR1 168
+#define AP_GW_ADDR2 43
+#define AP_GW_ADDR3 1
+#endif
+
+#if CONFIG_EXAMPLE_UART_ATCMD
+#include "wifi_structures.h"
+#include
+typedef struct _UART_LOG_CONF_{
+ u32 BaudRate;
+ u8 DataBits;
+ u8 StopBits;
+ u8 Parity;
+ u8 FlowControl;
+}UART_LOG_CONF, *PUART_LOG_CONF;
+
+#define ATCMD_WIFI_CONN_STORE_MAX_NUM (1)
+struct atcmd_wifi_conf{
+ int32_t auto_enable;
+ rtw_wifi_setting_t setting;
+ int32_t reconn_num;
+ int32_t reconn_last_index;
+ struct wlan_fast_reconnect reconn[ATCMD_WIFI_CONN_STORE_MAX_NUM];
+};
+
+#define ATCMD_LWIP_CONN_STORE_MAX_NUM (1)
+struct atcmd_lwip_conn_info{
+ int32_t role; //client, server or seed
+ uint32_t protocol; //tcp or udp
+ uint32_t remote_addr; //remote ip
+ uint32_t remote_port; //remote port
+ uint32_t local_addr; //locale ip, not used yet
+ uint32_t local_port; //locale port, not used yet
+ uint32_t reserved; //reserve for further use
+};
+struct atcmd_lwip_conf {
+ int32_t enable; //enable or not
+ int32_t conn_num;
+ int32_t last_index;
+ int32_t reserved; //reserve for further use
+ struct atcmd_lwip_conn_info conn[ATCMD_LWIP_CONN_STORE_MAX_NUM];
+};
+
+typedef enum {
+ AT_PARTITION_ALL = 0,
+ AT_PARTITION_UART = 1,
+ AT_PARTITION_WIFI = 2,
+ AT_PARTITION_LWIP = 3
+} AT_PARTITION;
+
+typedef enum {
+ AT_PARTITION_READ = 0,
+ AT_PARTITION_WRITE = 1,
+ AT_PARTITION_ERASE = 2
+} AT_PARTITION_OP;
+
+//first segment for uart
+#define UART_SETTING_BACKUP_SECTOR (0x8000)
+#define UART_CONF_DATA_OFFSET (0)
+#define UART_CONF_DATA_SIZE ((((sizeof(UART_LOG_CONF)-1)>>2) + 1)<<2)
+
+//second segment for wifi config
+#define WIFI_CONF_DATA_OFFSET (UART_CONF_DATA_OFFSET+UART_CONF_DATA_SIZE)
+#define WIFI_CONF_DATA_SIZE ((((sizeof(struct atcmd_wifi_conf)-1)>>2) + 1)<<2)
+
+//fouth segment for lwip config
+#define LWIP_CONF_DATA_OFFSET (WIFI_CONF_DATA_OFFSET+WIFI_CONF_DATA_SIZE)
+#define LWIP_CONF_DATA_SIZE ((((sizeof(struct atcmd_lwip_conf)-1)>>2) + 1)<<2)
+
+extern void atcmd_update_partition_info(AT_PARTITION id, AT_PARTITION_OP ops, u8 *data, u16 len);
+
+#define ATSTRING_LEN (LOG_SERVICE_BUFLEN)
+extern char at_string[ATSTRING_LEN];
+
+extern unsigned char gAT_Echo; // default echo on
+//extern void uart_at_lock(void);
+//extern void uart_at_unlock(void);
+extern void uart_at_send_string(char *str);
+extern void uart_at_send_buf(u8 *buf, u32 len);
+
+#define at_printf(fmt, args...) do{\
+ /*uart_at_lock();*/\
+ snprintf(at_string, ATSTRING_LEN, fmt, ##args); \
+ uart_at_send_string(at_string);\
+ /*uart_at_unlock();*/\
+ }while(0)
+#define at_print_data(data, size) do{\
+ /*uart_at_lock();*/\
+ uart_at_send_buf(data, size);\
+ /*uart_at_unlock();*/\
+ }while(0)
+
+#else
+#define at_printf(fmt, args...) do{printf(fmt, ##args);}while(0)
+#define at_print_data(data, size) do{__rtl_memDump(data, size, NULL);}while(0)
+#endif//#if CONFIG_EXAMPLE_UART_ATCMD
+
+#endif
diff --git a/RTLGDB/USDK/component/common/api/at_cmd/atcmd_wifi1.c b/RTLGDB/USDK/component/common/api/at_cmd/atcmd_wifi1.c
new file mode 100644
index 0000000..46dbc5b
--- /dev/null
+++ b/RTLGDB/USDK/component/common/api/at_cmd/atcmd_wifi1.c
@@ -0,0 +1,2873 @@
+#include
+#ifdef CONFIG_AT_WIFI
+
+#include "FreeRTOS.h"
+#include "task.h"
+#include "semphr.h"
+#include "log_service.h"
+#include "atcmd_wifi.h"
+#include
+#include "tcpip.h"
+#include
+#include "osdep_service.h"
+
+#if CONFIG_WLAN
+#include
+#include
+#include
+
+extern rtw_mode_t wifi_mode; // = RTW_MODE_STA;
+
+#endif
+
+/* Give default value if not defined */
+#ifndef NET_IF_NUM
+ #ifdef CONFIG_CONCURRENT_MODE
+ #define NET_IF_NUM ((CONFIG_ETHERNET) + (CONFIG_WLAN) + 1)
+ #else
+ #define NET_IF_NUM ((CONFIG_ETHERNET) + (CONFIG_WLAN))
+ #endif // end of CONFIG_CONCURRENT_MODE
+#endif // end of NET_IF_NUM
+
+#ifndef ATCMD_VER
+#define ATVER_1 1
+#define ATVER_2 2
+#define ATCMD_VER ATVER_2
+#if CONFIG_EXAMPLE_UART_ATCMD
+#define ATCMD_VER ATVER_2
+#else
+#define ATCMD_VER ATVER_1
+#endif
+#endif
+
+
+#if ATCMD_VER == ATVER_2
+#include "flash_api.h"
+#ifdef USE_FLASH_EEP
+#include "flash_eep.h"
+#endif
+#include "device_lock.h"
+#include
+#include
+#endif
+
+/******************************************************************************/
+#define _AT_WLAN_SET_SSID_ "ATW0"
+#define _AT_WLAN_SET_PASSPHRASE_ "ATW1"
+#define _AT_WLAN_SET_KEY_ID_ "ATW2"
+#define _AT_WLAN_AP_SET_SSID_ "ATW3"
+#define _AT_WLAN_AP_SET_SEC_KEY_ "ATW4"
+#define _AT_WLAN_AP_SET_CHANNEL_ "ATW5"
+#define _AT_WLAN_SET_BSSID_ "ATW6"
+#define _AT_WLAN_AP_ACTIVATE_ "ATWA"
+#define _AT_WLAN_AP_STA_ACTIVATE_ "ATWB"
+#define _AT_WLAN_JOIN_NET_ "ATWC"
+#define _AT_WLAN_DISC_NET_ "ATWD"
+#define _AT_WLAN_WEB_SERVER_ "ATWE"
+#define _AT_WLAN_P2P_FIND_ "ATWF"
+#define _AT_WLAN_P2P_START_ "ATWG"
+#define _AT_WLAN_P2P_STOP_ "ATWH"
+#define _AT_WLAN_PING_TEST_ "ATWI"
+#define _AT_WLAN_P2P_CONNECT_ "ATWJ"
+#define _AT_WLAN_P2P_DISCONNECT_ "ATWK"
+#define _AT_WLAN_SSL_CLIENT_ "ATWL"
+#define _AT_WLAN_PROMISC_ "ATWM"
+#define _AT_WLAN_P2P_INFO_ "ATWN"
+#define _AT_WLAN_OTA_UPDATE_ "ATWO"
+#define _AT_WLAN_POWER_ "ATWP"
+#define _AT_WLAN_SIMPLE_CONFIG_ "ATWQ"
+#define _AT_WLAN_GET_RSSI_ "ATWR"
+#define _AT_WLAN_SCAN_ "ATWS"
+#define _AT_WLAN_SCAN_WITH_SSID_ "ATWs"
+#define _AT_WLAN_TCP_TEST_ "ATWT"
+#define _AT_WLAN_UDP_TEST_ "ATWU"
+#define _AT_WLAN_WPS_ "ATWW"
+#define _AT_WLAN_AP_WPS_ "ATWw"
+#define _AT_WLAN_AIRKISS_ "ATWX"
+#define _AT_WLAN_IWPRIV_ "ATWZ"
+#define _AT_WLAN_INFO_ "ATW?"
+
+#define _AT_WLAN_EXTEND_POWER_MODE_ "ATXP"
+
+#ifndef CONFIG_SSL_CLIENT
+#define CONFIG_SSL_CLIENT 0
+#endif
+#ifndef CONFIG_WEBSERVER
+#define CONFIG_WEBSERVER 0
+#endif
+#ifndef CONFIG_OTA_UPDATE
+#define CONFIG_OTA_UPDATE 0
+#endif
+#ifndef CONFIG_BSD_TCP
+#define CONFIG_BSD_TCP 1
+#endif
+#ifndef CONFIG_ENABLE_P2P
+#define CONFIG_ENABLE_P2P 0
+#endif
+#define SCAN_WITH_SSID 0
+#if CONFIG_WEBSERVER
+#define CONFIG_READ_FLASH 1
+extern rtw_wifi_setting_t wifi_setting;
+#endif
+
+#ifndef CONFIG_WOWLAN_SERVICE
+#define CONFIG_WOWLAN_SERVICE 0
+#endif
+
+#if CONFIG_LWIP_LAYER
+extern void cmd_tcp(int argc, char **argv);
+extern void cmd_udp(int argc, char **argv);
+extern void cmd_ping(int argc, char **argv);
+extern void cmd_ssl_client(int argc, char **argv);
+#endif
+
+#if CONFIG_WLAN
+extern void cmd_promisc(int argc, char **argv);
+extern void cmd_update(int argc, char **argv);
+extern void cmd_simple_config(int argc, char **argv);
+#if CONFIG_ENABLE_WPS
+extern void cmd_wps(int argc, char **argv);
+#endif
+
+#if defined(CONFIG_ENABLE_WPS_AP) && CONFIG_ENABLE_WPS_AP
+extern void cmd_ap_wps(int argc, char **argv);
+extern int wpas_wps_dev_config(u8 *dev_addr, u8 bregistrar);
+#endif
+#if CONFIG_ENABLE_P2P
+extern void cmd_wifi_p2p_start(int argc, char **argv);
+extern void cmd_wifi_p2p_stop(int argc, char **argv);
+extern void cmd_p2p_listen(int argc, char **argv);
+extern void cmd_p2p_find(int argc, char **argv);
+extern void cmd_p2p_peers(int argc, char **argv);
+extern void cmd_p2p_info(int argc, char **argv);
+extern void cmd_p2p_disconnect(int argc, char **argv);
+extern void cmd_p2p_connect(int argc, char **argv);
+extern int cmd_wifi_p2p_auto_go_start(int argc, char **argv);
+#endif //CONFIG_ENABLE_P2P
+#if CONFIG_AIRKISS
+extern int airkiss_start();
+#endif
+#if CONFIG_LWIP_LAYER
+extern struct netif xnetif[NET_IF_NUM];
+#endif
+#if CONFIG_WOWLAN_SERVICE
+extern void cmd_wowlan_service(int argc, char **argv);
+#endif
+#if CONFIG_INIC_CMD_RSP
+extern void inic_c2h_wifi_info(const char *atcmd, char status);
+extern void inic_c2h_msg(const char *atcmd, u8 status, char *msg, u16 msg_len);
+#endif
+
+/* fastconnect use wifi AT command. Not init_wifi_struct when log service disabled
+ * static initialize all values for using fastconnect when log service disabled
+ */
+static rtw_network_info_t wifi = {
+ {0}, // ssid
+ {0}, // bssid
+ 0, // security
+ NULL, // password
+ 0, // password len
+ -1 // key id
+};
+
+static rtw_ap_info_t ap = {0};
+static unsigned char password[65] = {0};
+
+#if ATCMD_VER == ATVER_2
+unsigned char dhcp_mode_sta = 1, dhcp_mode_ap = 1;
+unsigned char sta_ip[4] = {192,168,3,80}, sta_netmask[4] = {255,255,255,0}, sta_gw[4] = {192,168,3,1};
+unsigned char ap_ip[4] = {192,168,43,1}, ap_netmask[4] = {255,255,255,0}, ap_gw[4] = {192,168,43,1};
+#endif
+
+
+static void init_wifi_struct(void)
+{
+ memset(wifi.ssid.val, 0, sizeof(wifi.ssid.val));
+ memset(wifi.bssid.octet, 0, ETH_ALEN);
+ memset(password, 0, sizeof(password));
+ wifi.ssid.len = 0;
+ wifi.password = NULL;
+ wifi.password_len = 0;
+ wifi.key_id = -1;
+ memset(ap.ssid.val, 0, sizeof(ap.ssid.val));
+ ap.ssid.len = 0;
+ ap.password = NULL;
+ ap.password_len = 0;
+ ap.channel = 1;
+}
+
+static void print_scan_result( rtw_scan_result_t* record )
+{
+#if CONFIG_EXAMPLE_UART_ATCMD
+ at_printf("%s,%d,%s,%d,"MAC_FMT"", record->SSID.val, record->channel,
+ ( record->security == RTW_SECURITY_OPEN ) ? "Open" :
+ ( record->security == RTW_SECURITY_WEP_PSK ) ? "WEP" :
+ ( record->security == RTW_SECURITY_WPA_TKIP_PSK ) ? "WPA TKIP" :
+ ( record->security == RTW_SECURITY_WPA_AES_PSK ) ? "WPA AES" :
+ ( record->security == RTW_SECURITY_WPA2_AES_PSK ) ? "WPA2 AES" :
+ ( record->security == RTW_SECURITY_WPA2_TKIP_PSK ) ? "WPA2 TKIP" :
+ ( record->security == RTW_SECURITY_WPA2_MIXED_PSK ) ? "WPA2 Mixed" :
+ ( record->security == RTW_SECURITY_WPA_WPA2_MIXED ) ? "WPA/WPA2 AES" : "Unknown",
+ record->signal_strength, MAC_ARG(record->BSSID.octet) );
+#else
+ RTW_API_INFO( ( "%s\t ", ( record->bss_type == RTW_BSS_TYPE_ADHOC ) ? "Adhoc" : "Infra" ) );
+ RTW_API_INFO( ( MAC_FMT, MAC_ARG(record->BSSID.octet) ) );
+ RTW_API_INFO( ( " %d\t ", record->signal_strength ) );
+ RTW_API_INFO( ( " %d\t ", record->channel ) );
+ RTW_API_INFO( ( " %d\t ", record->wps_type ) );
+ RTW_API_INFO( ( "%s\t\t ", ( record->security == RTW_SECURITY_OPEN ) ? "Open" :
+ ( record->security == RTW_SECURITY_WEP_PSK ) ? "WEP" :
+ ( record->security == RTW_SECURITY_WPA_TKIP_PSK ) ? "WPA TKIP" :
+ ( record->security == RTW_SECURITY_WPA_AES_PSK ) ? "WPA AES" :
+ ( record->security == RTW_SECURITY_WPA2_AES_PSK ) ? "WPA2 AES" :
+ ( record->security == RTW_SECURITY_WPA2_TKIP_PSK ) ? "WPA2 TKIP" :
+ ( record->security == RTW_SECURITY_WPA2_MIXED_PSK ) ? "WPA2 Mixed" :
+ ( record->security == RTW_SECURITY_WPA_WPA2_MIXED ) ? "WPA/WPA2 AES" :
+ "Unknown" ) );
+
+ RTW_API_INFO( ( " %s ", record->SSID.val ) );
+ RTW_API_INFO( ( "\r\n" ) );
+#endif
+}
+
+static rtw_result_t app_scan_result_handler( rtw_scan_handler_result_t* malloced_scan_result )
+{
+ static int ApNum = 0;
+
+ if (malloced_scan_result->scan_complete != RTW_TRUE) {
+ rtw_scan_result_t* record = &malloced_scan_result->ap_details;
+ record->SSID.val[record->SSID.len] = 0; /* Ensure the SSID is null terminated */
+
+#if CONFIG_EXAMPLE_UART_ATCMD
+ at_printf("\r\nAP : %d,", ++ApNum);
+#else
+ RTW_API_INFO( ( "%d\t ", ++ApNum ) );
+#endif
+ print_scan_result(record);
+#if CONFIG_INIC_CMD_RSP
+ if(malloced_scan_result->user_data)
+ memcpy((void *)((char *)malloced_scan_result->user_data+(ApNum-1)*sizeof(rtw_scan_result_t)), (char *)record, sizeof(rtw_scan_result_t));
+#endif
+ } else{
+#if CONFIG_INIC_CMD_RSP
+ inic_c2h_msg("ATWS", RTW_SUCCESS, (char *)malloced_scan_result->user_data, ApNum*sizeof(rtw_scan_result_t));
+ if(malloced_scan_result->user_data)
+ free(malloced_scan_result->user_data);
+ inic_c2h_msg("ATWS", RTW_SUCCESS, NULL, 0);
+#endif
+#if CONFIG_EXAMPLE_UART_ATCMD
+ at_printf("\r\n[ATWS] OK");
+ at_printf(STR_END_OF_ATCMD_RET);
+#endif
+ ApNum = 0;
+ }
+ return RTW_SUCCESS;
+}
+
+// WIFI disconnect
+void fATWD(void *arg){
+ int timeout = 10000/200;
+ char essid[33];
+ int ret = RTW_SUCCESS;
+#if ATCMD_VER == ATVER_2
+ int error_no = 0;
+#endif
+
+ printf("[ATWD]: _AT_WLAN_DISC_NET_\n");
+ printf("Deassociating AP ...\n");
+
+ if(wext_get_ssid(WLAN0_NAME, (unsigned char *) essid) < 0) {
+ printf("WIFI disconnected\n");
+ goto exit_success;
+ }
+
+ if((ret = wifi_disconnect()) < 0) {
+ printf("ERROR: Operation failed!\n");
+#if ATCMD_VER == ATVER_2
+ error_no = 3;
+#endif
+ goto exit;
+ }
+
+ while(1) {
+ if(wext_get_ssid(WLAN0_NAME, (unsigned char *) essid) < 0) {
+ printf("WIFI disconnected\n");
+ break;
+ }
+
+ if(timeout == 0) {
+ printf("ERROR: Deassoc timeout!\n");
+ ret = RTW_TIMEOUT;
+#if ATCMD_VER == ATVER_2
+ error_no = 4;
+#endif
+ break;
+ }
+// vTaskDelay(1 * configTICK_RATE_HZ);
+ vTaskDelay(200/portTICK_RATE_MS);
+ timeout --;
+ }
+ printf("\n");
+exit:
+#if CONFIG_INIC_CMD_RSP
+ if(ret != RTW_SUCCESS)
+ inic_c2h_msg("ATWD", ret, NULL, 0);
+#endif
+ init_wifi_struct( );
+#if ATCMD_VER == ATVER_2
+ if(error_no==0)
+ at_printf("\r\n[ATWD] OK");
+ else
+ at_printf("\r\n[ATWD] ERROR:%d",error_no);
+#endif
+ return;
+exit_success:
+#if CONFIG_INIC_CMD_RSP
+ inic_c2h_msg("ATWD", RTW_SUCCESS, NULL, 0);
+#endif
+ init_wifi_struct( );
+#if ATCMD_VER == ATVER_2
+ at_printf("\r\n[ATWD] OK");
+#endif
+ return;
+}
+
+// wifi simpleconfig
+#if (CONFIG_INCLUDE_SIMPLE_CONFIG)
+void fATWQ(void *arg){
+ int argc=0;
+ char *argv[2] = {0};
+ printf("[ATWQ]: _AT_WLAN_SIMPLE_CONFIG_\n");
+ argv[argc++] = "wifi_simple_config";
+ if(arg){
+ argv[argc++] = arg;
+ }
+ cmd_simple_config(argc, argv);
+}
+#endif
+
+// WIFI scan
+void fATWS(void *arg){
+ char buf[32] = {0};
+ u8 *channel_list = NULL;
+ u8 *pscan_config = NULL;
+ int num_channel = 0;
+ int i, argc = 0;
+ char *argv[MAX_ARGC] = {0};
+ int ret = RTW_SUCCESS;
+#if CONFIG_INIC_CMD_RSP
+ u8 *inic_scan_buf = NULL;
+#endif
+#if ATCMD_VER == ATVER_2
+ int error_no = 0;
+#endif
+ printf("[ATWS]: _AT_WLAN_SCAN_\n");
+ if(arg){
+ strcpy(buf, arg);
+ argc = parse_param(buf, argv);
+ if(argc < 2){
+ ret = RTW_BADARG;
+#if ATCMD_VER == ATVER_2
+ error_no = 1;
+#endif
+ goto exit;
+ }
+ num_channel = atoi(argv[1]);
+ channel_list = (u8*)malloc(num_channel);
+ if(!channel_list){
+ printf("[ATWS]ERROR: Can't malloc memory for channel list\n");
+ ret = RTW_BUFFER_UNAVAILABLE_TEMPORARY;
+#if ATCMD_VER == ATVER_2
+ error_no = 2;
+#endif
+ goto exit;
+ }
+ pscan_config = (u8*)malloc(num_channel);
+ if(!pscan_config){
+ printf("[ATWS]ERROR: Can't malloc memory for pscan_config\n");
+ ret = RTW_BUFFER_UNAVAILABLE_TEMPORARY;
+#if ATCMD_VER == ATVER_2
+ error_no = 3;
+#endif
+ goto exit;
+ }
+ //parse command channel list
+ for(i = 2; i <= argc -1 ; i++){
+ *(channel_list + i - 2) = (u8)atoi(argv[i]);
+ *(pscan_config + i - 2) = PSCAN_ENABLE;
+ }
+
+ if((ret = wifi_set_pscan_chan(channel_list, pscan_config, num_channel)) < 0){
+ printf("[ATWS]ERROR: wifi set partial scan channel fail\n");
+#if ATCMD_VER == ATVER_2
+ error_no = 4;
+#endif
+ goto exit;
+ }
+ }
+#if CONFIG_INIC_CMD_RSP
+ inic_scan_buf = malloc(65*sizeof(rtw_scan_result_t));
+ if(inic_scan_buf == NULL){
+ ret = RTW_BUFFER_UNAVAILABLE_TEMPORARY;
+ goto exit;
+ }
+ memset(inic_scan_buf, 0, 65*sizeof(rtw_scan_result_t));
+ if((ret = wifi_scan_networks(app_scan_result_handler, inic_scan_buf)) != RTW_SUCCESS){
+ printf("[ATWS]ERROR: wifi scan failed\n");
+ goto exit;
+ }
+#else
+ if((ret = wifi_scan_networks(app_scan_result_handler, NULL )) != RTW_SUCCESS){
+ printf("[ATWS]ERROR: wifi scan failed\n");
+#if ATCMD_VER == ATVER_2
+ error_no = 5;
+#endif
+ goto exit;
+ }
+#endif
+exit:
+#if CONFIG_INIC_CMD_RSP
+ if(ret != RTW_SUCCESS){
+ if(inic_scan_buf)
+ free(inic_scan_buf);
+ inic_c2h_msg("ATWS", ret, NULL, 0);
+ }
+#endif
+#if ATCMD_VER == ATVER_2
+ if(error_no)
+ at_printf("[ATWS] ERROR:%d\n",error_no);
+#endif
+ if(arg && channel_list)
+ free(channel_list);
+ if(arg && pscan_config)
+ free(pscan_config);
+}
+
+void fATWx(void *arg){
+ int i = 0;
+#if CONFIG_LWIP_LAYER
+ u8 *mac = LwIP_GetMAC(&xnetif[0]);
+ u8 *ip = LwIP_GetIP(&xnetif[0]);
+ u8 *gw = LwIP_GetGW(&xnetif[0]);
+#endif
+ u8 *ifname[2] = {WLAN0_NAME,WLAN1_NAME};
+ rtw_wifi_setting_t setting;
+
+ printf("[ATW?]: _AT_WLAN_INFO_\n");
+#if CONFIG_INIC_CMD_RSP
+ int ret = RTW_SUCCESS;
+ int info_sz = 0;
+ u8 *info = malloc(NET_IF_NUM*sizeof(rtw_wifi_setting_t)+3*sizeof(rtw_mac_t));
+ if(info == NULL)
+ ret = RTW_BUFFER_UNAVAILABLE_TEMPORARY;
+#endif
+ for(i=0;i %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]) ;
+ printf("\tIP => %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
+ printf("\tGW => %d.%d.%d.%d\n", gw[0], gw[1], gw[2], gw[3]);
+#endif
+ if(setting.mode == RTW_MODE_AP || i == 1)
+ {
+ int client_number;
+ struct {
+ int count;
+ rtw_mac_t mac_list[AP_STA_NUM];
+ } client_info;
+
+ client_info.count = AP_STA_NUM;
+ wifi_get_associated_client_list(&client_info, sizeof(client_info));
+
+ printf("Associated Client List:\n");
+ printf("==============================\n");
+
+ if(client_info.count == 0)
+ printf("Client Num: 0\n", client_info.count);
+ else
+ {
+ printf("Client Num: %d\n", client_info.count);
+ for( client_number=0; client_number < client_info.count; client_number++ )
+ {
+ printf("Client %d:\n", client_number + 1);
+ printf("\tMAC => "MAC_FMT"\n",
+ MAC_ARG(client_info.mac_list[client_number].octet));
+#if CONFIG_EXAMPLE_UART_ATCMD
+ at_printf("CLIENT:%d,"MAC_FMT"\n", client_number + 1, MAC_ARG(client_info.mac_list[client_number].octet));
+#endif
+#if CONFIG_INIC_CMD_RSP
+ if(info){
+ memcpy(info+info_sz, (void *)&client_info.mac_list[client_number], sizeof(rtw_mac_t));
+ info_sz += sizeof(rtw_mac_t);
+ }
+#endif
+ }
+ printf("\n\r");
+ }
+ }
+ }
+// show the ethernet interface info
+ else
+ {
+#if CONFIG_ETHERNET
+ if(i == NET_IF_NUM - 1)
+ {
+#if CONFIG_LWIP_LAYER
+ mac = LwIP_GetMAC(&xnetif[i]);
+ ip = LwIP_GetIP(&xnetif[i]);
+ gw = LwIP_GetGW(&xnetif[i]);
+ printf("\nInterface ethernet\n");
+ printf("==============================\n");
+ printf("\tMAC => %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]) ;
+ printf("\tIP => %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
+ printf("\tGW => %d.%d.%d.%d\n", gw[0], gw[1], gw[2], gw[3]);
+#endif // end CONFIG_LWIP_LAYER
+ }
+#endif // end CONFIG_ETHERNET
+ }
+ }
+
+#if defined(configUSE_TRACE_FACILITY) && (configUSE_TRACE_FACILITY == 1) && (configUSE_STATS_FORMATTING_FUNCTIONS == 1)
+ {
+ char * pcWriteBuffer = malloc(1024);
+ if(pcWriteBuffer) {
+ vTaskList((char*)pcWriteBuffer);
+ printf("\nTask List:\n");
+ printf("==============================\n");
+ printf("Name\t Status Priority HighWaterMark TaskNumber\n%s\n", pcWriteBuffer);
+ free(pcWriteBuffer);
+ }
+ }
+#endif
+
+#if CONFIG_INIC_CMD_RSP
+ if(ret != RTW_SUCCESS)
+ inic_c2h_msg("ATW?", ret, NULL, 0);
+ else
+ inic_c2h_msg("ATW?", RTW_SUCCESS, (char *)info, info_sz);
+
+ if(info)
+ free(info);
+ info = NULL;
+#endif
+
+#if CONFIG_EXAMPLE_UART_ATCMD
+ at_printf("\r\n[ATW?] OK");
+#endif
+
+}
+
+#if ATCMD_VER == ATVER_1
+void fATW0(void *arg){
+ int ret = RTW_SUCCESS;
+ if(!arg){
+ printf("[ATW0]Usage: ATW0=SSID\n");
+ ret = RTW_BADARG;
+ goto exit;
+ }
+ printf("[ATW0]: _AT_WLAN_SET_SSID_ [%s]\n", (char*)arg);
+ strcpy((char *)wifi.ssid.val, (char*)arg);
+ wifi.ssid.len = strlen((char*)arg);
+exit:
+#if CONFIG_INIC_CMD_RSP
+ inic_c2h_msg("ATW0", ret, NULL, 0);
+#endif
+ return;
+}
+
+void fATW1(void *arg){
+ int ret = RTW_SUCCESS;
+ printf("[ATW1]: _AT_WLAN_SET_PASSPHRASE_ [%s]\n", (char*)arg);
+ strcpy((char *)password, (char*)arg);
+ wifi.password = password;
+ wifi.password_len = strlen((char*)arg);
+exit:
+#if CONFIG_INIC_CMD_RSP
+ inic_c2h_msg("ATW1", ret, NULL, 0);
+#endif
+ return;
+}
+
+void fATW2(void *arg){
+ int ret = RTW_SUCCESS;
+ printf("[ATW2]: _AT_WLAN_SET_KEY_ID_ [%s]\n", (char*)arg);
+ if((strlen((const char *)arg) != 1 ) || (*(char*)arg <'0' ||*(char*)arg >'3')) {
+ printf("Wrong WEP key id. Must be one of 0,1,2, or 3.\n");
+ ret = RTW_BADARG;
+ goto exit;
+ }
+ wifi.key_id = atoi((const char *)(arg));
+exit:
+#if CONFIG_INIC_CMD_RSP
+ inic_c2h_msg("ATW2", ret, NULL, 0);
+#endif
+ return;
+}
+
+void fATW3(void *arg){
+ int ret = RTW_SUCCESS;
+ if(!arg){
+ printf("[ATW3]Usage: ATW3=SSID\n");
+ ret = RTW_BADARG;
+ goto exit;
+ }
+
+ ap.ssid.len = strlen((char*)arg);
+
+ if(ap.ssid.len > 32){
+ printf("[ATW3]Error: SSID length can't exceed 32\n");
+ ret = RTW_BADARG;
+ goto exit;
+ }
+ strcpy((char *)ap.ssid.val, (char*)arg);
+
+ printf("[ATW3]: _AT_WLAN_AP_SET_SSID_ [%s]\n", ap.ssid.val);
+exit:
+#if CONFIG_INIC_CMD_RSP
+ inic_c2h_msg("ATW3", ret, NULL, 0);
+#endif
+ return;
+}
+
+void fATW4(void *arg){
+ int ret = RTW_SUCCESS;
+ strcpy((char *)password, (char*)arg);
+ ap.password = password;
+ ap.password_len = strlen((char*)arg);
+ printf("[ATW4]: _AT_WLAN_AP_SET_SEC_KEY_ [%s]\n", ap.password);
+exit:
+#if CONFIG_INIC_CMD_RSP
+ inic_c2h_msg("ATW4", ret, NULL, 0);
+#endif
+ return;
+}
+
+void fATW5(void *arg){
+ int ret = RTW_SUCCESS;
+ ap.channel = (unsigned char) atoi((const char *)arg);
+ printf("[ATW5]: _AT_WLAN_AP_SET_CHANNEL_ [channel %d]\n", ap.channel);
+exit:
+#if CONFIG_INIC_CMD_RSP
+ inic_c2h_msg("ATW5", ret, NULL, 0);
+#endif
+ return;
+}
+
+void fATW6(void *arg){
+ u32 mac[ETH_ALEN];
+ u32 i;
+ int ret = RTW_SUCCESS;
+ if(!arg){
+ printf("[ATW6]Usage: ATW6=BSSID\n");
+ ret = RTW_BADARG;
+ goto exit;
+ }
+ printf("[ATW6]: _AT_WLAN_SET_BSSID_ [%s]\n", (char*)arg);
+ sscanf(arg, MAC_FMT, mac, mac + 1, mac + 2, mac + 3, mac + 4, mac + 5);
+ for(i = 0; i < ETH_ALEN; i ++)
+ wifi.bssid.octet[i] = (u8)mac[i] & 0xFF;
+exit:
+#if CONFIG_INIC_CMD_RSP
+ inic_c2h_msg("ATW6", ret, NULL, 0);
+#endif
+ return;
+}
+
+void fATWA(void *arg){
+#if CONFIG_LWIP_LAYER
+ struct ip_addr ipaddr;
+ struct ip_addr netmask;
+ struct ip_addr gw;
+ struct netif * pnetif = &xnetif[0];
+#endif
+ int timeout = 10000/200;
+ int ret = RTW_SUCCESS;
+ printf("[ATWA]: _AT_WLAN_AP_ACTIVATE_\n");
+ if(ap.ssid.val[0] == 0){
+ printf("[ATWA]Error: SSID can't be empty\n");
+ ret = RTW_BADARG;
+ goto exit;
+ }
+ if(ap.password == NULL){
+ ap.security_type = RTW_SECURITY_OPEN;
+ }
+ else{
+ ap.security_type = RTW_SECURITY_WPA2_AES_PSK;
+ }
+
+#if CONFIG_WEBSERVER
+ //store into flash
+ memset(wifi_setting.ssid, 0, sizeof(wifi_setting.ssid));;
+ memcpy(wifi_setting.ssid, ap.ssid.val, strlen((char*)ap.ssid.val));
+ wifi_setting.ssid[ap.ssid.len] = '\0';
+ wifi_setting.security_type = ap.security_type;
+ if(ap.security_type !=0)
+ wifi_setting.security_type = 1;
+ else
+ wifi_setting.security_type = 0;
+ if (ap.password)
+ memcpy(wifi_setting.password, ap.password, strlen((char*)ap.password));
+ else
+ memset(wifi_setting.password, 0, sizeof(wifi_setting.password));
+ wifi_setting.channel = ap.channel;
+#if CONFIG_READ_FLASH
+ StoreApInfo();
+#endif
+#endif
+
+#if CONFIG_LWIP_LAYER
+ dhcps_deinit();
+ IP4_ADDR(&ipaddr, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
+ IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1 , NETMASK_ADDR2, NETMASK_ADDR3);
+ IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
+ netif_set_addr(pnetif, &ipaddr, &netmask,&gw);
+#ifdef CONFIG_DONT_CARE_TP
+ pnetif->flags |= NETIF_FLAG_IPSWITCH;
+#endif
+#endif
+ wifi_off();
+ vTaskDelay(20);
+ if (wifi_on(RTW_MODE_AP) < 0){
+ printf("ERROR: Wifi on failed!\n");
+ ret = RTW_ERROR;
+ goto exit;
+ }
+ printf("Starting AP ...\n");
+
+#if defined(CONFIG_ENABLE_WPS_AP) && CONFIG_ENABLE_WPS_AP
+ wpas_wps_dev_config(pnetif->hwaddr, 1);
+#endif
+ if((ret = wifi_start_ap((char*)ap.ssid.val, ap.security_type, (char*)ap.password, ap.ssid.len, ap.password_len, ap.channel) )< 0) {
+ printf("ERROR: Operation failed!\n");
+ goto exit;
+ }
+
+ while(1) {
+ char essid[33];
+
+ if(wext_get_ssid(WLAN0_NAME, (unsigned char *) essid) > 0) {
+ if(strcmp((const char *) essid, (const char *)ap.ssid.val) == 0) {
+ printf("%s started\n", ap.ssid.val);
+ ret = RTW_SUCCESS;
+ break;
+ }
+ }
+
+ if(timeout == 0) {
+ printf("ERROR: Start AP timeout!\n");
+ ret = RTW_TIMEOUT;
+ break;
+ }
+ //vTaskDelay(1 * configTICK_RATE_HZ);
+ vTaskDelay(200/portTICK_RATE_MS);
+ timeout --;
+ }
+#if CONFIG_LWIP_LAYER
+ //LwIP_UseStaticIP(pnetif);
+ dhcps_init(pnetif);
+#endif
+
+exit:
+#if CONFIG_INIC_CMD_RSP
+ inic_c2h_wifi_info("ATWA", ret);
+#endif
+ init_wifi_struct( );
+}
+
+#if CONFIG_INIC_EN
+static int _find_ap_from_scan_buf(char*buf, int buflen, char *target_ssid, void *user_data)
+{
+ rtw_wifi_setting_t *pwifi = (rtw_wifi_setting_t *)user_data;
+ int plen = 0;
+
+ while(plen < buflen){
+ u8 len, ssid_len, security_mode;
+ char *ssid;
+
+ // len offset = 0
+ len = (int)*(buf + plen);
+ // check end
+ if(len == 0) break;
+ // ssid offset = 14
+ ssid_len = len - 14;
+ ssid = buf + plen + 14 ;
+ if((ssid_len == strlen(target_ssid))
+ && (!memcmp(ssid, target_ssid, ssid_len)))
+ {
+ strcpy((char*)pwifi->ssid, target_ssid);
+ // channel offset = 13
+ pwifi->channel = *(buf + plen + 13);
+ // security_mode offset = 11
+ security_mode = (u8)*(buf + plen + 11);
+ if(security_mode == IW_ENCODE_ALG_NONE)
+ pwifi->security_type = RTW_SECURITY_OPEN;
+ else if(security_mode == IW_ENCODE_ALG_WEP)
+ pwifi->security_type = RTW_SECURITY_WEP_PSK;
+ else if(security_mode == IW_ENCODE_ALG_CCMP)
+ pwifi->security_type = RTW_SECURITY_WPA2_AES_PSK;
+ break;
+ }
+ plen += len;
+ }
+ return 0;
+}
+
+static int _get_ap_security_mode(IN char * ssid, OUT rtw_security_t *security_mode, OUT u8 * channel)
+{
+ rtw_wifi_setting_t wifi;
+ u32 scan_buflen = 1000;
+
+ memset(&wifi, 0, sizeof(wifi));
+
+ if(wifi_scan_networks_with_ssid(_find_ap_from_scan_buf, (void*)&wifi, scan_buflen, ssid, strlen(ssid)) != RTW_SUCCESS){
+ printf("Wifi scan failed!\n");
+ return 0;
+ }
+
+ if(strcmp(wifi.ssid, ssid) == 0){
+ *security_mode = wifi.security_type;
+ *channel = wifi.channel;
+ return 1;
+ }
+
+ return 0;
+}
+#endif
+
+void fATWC(void *arg){
+ int mode, ret;
+ unsigned long tick1 = xTaskGetTickCount();
+ unsigned long tick2, tick3;
+ char empty_bssid[6] = {0}, assoc_by_bssid = 0;
+
+ printf("[ATWC]: _AT_WLAN_JOIN_NET_\n");
+ if(memcmp (wifi.bssid.octet, empty_bssid, 6))
+ assoc_by_bssid = 1;
+ else if(wifi.ssid.val[0] == 0){
+ printf("[ATWC]Error: SSID can't be empty\n");
+ ret = RTW_BADARG;
+ goto EXIT;
+ }
+ if(wifi.password != NULL){
+ if((wifi.key_id >= 0)&&(wifi.key_id <= 3)) {
+ wifi.security_type = RTW_SECURITY_WEP_PSK;
+ }
+ else{
+ wifi.security_type = RTW_SECURITY_WPA2_AES_PSK;
+ }
+ }
+ else{
+ wifi.security_type = RTW_SECURITY_OPEN;
+ }
+ //Check if in AP mode
+ wext_get_mode(WLAN0_NAME, &mode);
+ if(mode == IW_MODE_MASTER) {
+#if CONFIG_LWIP_LAYER
+ dhcps_deinit();
+#endif
+ wifi_off();
+ vTaskDelay(20);
+ if (wifi_on(RTW_MODE_STA) < 0){
+ printf("ERROR: Wifi on failed!\n");
+ ret = RTW_ERROR;
+ goto EXIT;
+ }
+ }
+
+#if CONFIG_INIC_EN //get security mode from scan list
+ u8 connect_channel;
+ u8 pscan_config;
+ //the keyID may be not set for WEP which may be confued with WPA2
+ if((wifi.security_type == RTW_SECURITY_UNKNOWN)||(wifi.security_type == RTW_SECURITY_WPA2_AES_PSK))
+ {
+ int security_retry_count = 0;
+ while (1) {
+ if (_get_ap_security_mode((char*)wifi.ssid.val, &wifi.security_type, &connect_channel))
+ break;
+ security_retry_count++;
+ if(security_retry_count >= 3){
+ printf("Can't get AP security mode and channel.\n");
+ ret = RTW_NOTFOUND;
+ goto EXIT;
+ }
+ }
+ if(wifi.security_type == RTW_SECURITY_WEP_PSK || wifi.security_type == RTW_SECURITY_WEP_SHARED)
+ wifi.key_id = (wifi.key_id <0 || wifi.key_id >3)?0:wifi.key_id;
+#if 0 //implemented in wifi_connect()
+ //hex to ascii conversion
+ if(wifi.security_type == RTW_SECURITY_WEP_PSK)
+ {
+ if(wifi.password_len == 10)
+ {
+ u32 p[5];
+ u8 pwd[6], i = 0;
+ sscanf((const char*)wifi.password, "%02x%02x%02x%02x%02x", &p[0], &p[1], &p[2], &p[3], &p[4]);
+ for(i=0; i< 5; i++)
+ pwd[i] = (u8)p[i];
+ pwd[5] = '\0';
+ memset(wifi.password, 0, 65);
+ strcpy((char*)wifi.password, (char*)pwd);
+ wifi.password_len = 5;
+ }else if(wifi.password_len == 26){
+ u32 p[13];
+ u8 pwd[14], i = 0;
+ sscanf((const char*)wifi.password, "%02x%02x%02x%02x%02x%02x%02x"\
+ "%02x%02x%02x%02x%02x%02x", &p[0], &p[1], &p[2], &p[3], &p[4],\
+ &p[5], &p[6], &p[7], &p[8], &p[9], &p[10], &p[11], &p[12]);
+ for(i=0; i< 13; i++)
+ pwd[i] = (u8)p[i];
+ pwd[13] = '\0';
+ memset(wifi.password, 0, 65);
+ strcpy((char*)wifi.password, (char*)pwd);
+ wifi.password_len = 13;
+ }
+ }
+#endif
+ }
+ pscan_config = PSCAN_ENABLE;
+ if(connect_channel > 0 && connect_channel < 14)
+ wifi_set_pscan_chan(&connect_channel, &pscan_config, 1);
+#endif
+
+ if(assoc_by_bssid){
+ printf("Joining BSS by BSSID "MAC_FMT" ...\n", MAC_ARG(wifi.bssid.octet));
+ } else {
+ printf("Joining BSS by SSID %s...\n", (char*)wifi.ssid.val);
+ }
+ ret = wifi_connect(wifi.bssid.octet,
+ assoc_by_bssid,
+ (char*)wifi.ssid.val,
+ wifi.security_type,
+ (char*)wifi.password,
+ wifi.key_id,
+ NULL);
+
+ if(ret!= RTW_SUCCESS){
+ printf("ERROR: Can't connect to AP\n");
+ goto EXIT;
+ }
+ tick2 = xTaskGetTickCount();
+ printf("Connected after %dms.\n", (tick2-tick1));
+#if CONFIG_LWIP_LAYER
+ /* Start DHCPClient */
+ LwIP_DHCP(0, DHCP_START);
+ tick3 = xTaskGetTickCount();
+ printf("Got IP after %dms.\n", (tick3-tick1));
+#endif
+// printf("\n\r");
+EXIT:
+#if CONFIG_INIC_CMD_RSP
+ inic_c2h_wifi_info("ATWC", ret);
+#endif
+
+ init_wifi_struct( );
+}
+
+#if SCAN_WITH_SSID
+void fATWs(void *arg){
+ char buf[32] = {0};
+ u8 *channel_list = NULL;
+ u8 *pscan_config = NULL;
+ int scan_buf_len = 500;
+ int num_channel = 0;
+ int i, argc = 0;
+ char *argv[MAX_ARGC] = {0};
+ printf("[ATWs]: _AT_WLAN_SCAN_WITH_SSID_ [%s]\n", (char*)wifi.ssid.val);
+ if(arg){
+ strcpy(buf, arg);
+ argc = parse_param(buf, argv);
+ if(argc == 2){
+ scan_buf_len = atoi(argv[1]);
+ if(scan_buf_len < 36){
+ printf("[ATWs] BUFFER_LENGTH too short\n");
+ goto exit;
+ }
+ }else if(argc > 2){
+ num_channel = atoi(argv[1]);
+ channel_list = (u8*)malloc(num_channel);
+ if(!channel_list){
+ printf("[ATWs]ERROR: Can't malloc memory for channel list\n");
+ goto exit;
+ }
+ pscan_config = (u8*)malloc(num_channel);
+ if(!pscan_config){
+ printf("[ATWs]ERROR: Can't malloc memory for pscan_config\n");
+ goto exit;
+ }
+ //parse command channel list
+ for(i = 2; i <= argc -1 ; i++){
+ *(channel_list + i - 2) = (u8)atoi(argv[i]);
+ *(pscan_config + i - 2) = PSCAN_ENABLE;
+ }
+
+ if(wifi_set_pscan_chan(channel_list, pscan_config, num_channel) < 0){
+ printf("[ATWs]ERROR: wifi set partial scan channel fail\n");
+ goto exit;
+ }
+ }
+ }else{
+ printf("[ATWs]For Scan all channel Usage: ATWs=BUFFER_LENGTH\n");
+ printf("[ATWs]For Scan partial channel Usage: ATWs=num_channels[channel_num1, ...]\n");
+ goto exit;
+ }
+
+ if(wifi_scan_networks_with_ssid(NULL, NULL, scan_buf_len, (char*)wifi.ssid.val, wifi.ssid.len) != RTW_SUCCESS){
+ printf("[ATWs]ERROR: wifi scan failed\n");
+ }
+exit:
+ init_wifi_struct( );
+ if(arg && channel_list)
+ free(channel_list);
+ if(arg && pscan_config)
+ free(pscan_config);
+}
+#endif
+
+void fATWR(void *arg){
+ int rssi = 0;
+ printf("[ATWR]: _AT_WLAN_GET_RSSI_\n");
+ wifi_get_rssi(&rssi);
+ printf("wifi_get_rssi: rssi = %d\n", rssi);
+// printf("");
+}
+
+void fATWP(void *arg){
+ unsigned int parm = atoi((const char *)(arg));
+ printf("[ATWP]: _AT_WLAN_POWER_[%s]\n", parm?"ON":"OFF");
+ if(parm == 1){
+ if(wifi_on(RTW_MODE_STA)<0){
+ printf("ERROR: Wifi on failed!\n");
+ }
+ }
+ else if(parm == 0)
+ {
+#if CONFIG_WEBSERVER
+ stop_web_server();
+#endif
+ wifi_off();
+ }
+ else
+ printf("[ATWP]Usage: ATWP=0/1\n");
+}
+
+#if CONFIG_WOWLAN_SERVICE
+//for wowlan setting
+void fATWV(void *arg){
+ int argc;
+ char *argv[MAX_ARGC] = {0};
+
+ printf("[ATWV]: _AT_WLAN_WOWLAN_\n");
+
+ argc = parse_param(arg, argv);
+
+ cmd_wowlan_service(argc, argv);
+
+ return;
+}
+#endif
+
+#ifdef CONFIG_CONCURRENT_MODE
+void fATWB(void *arg)
+{
+ int timeout = 10000/200;
+ int ret = RTW_SUCCESS;
+#if CONFIG_LWIP_LAYER
+ struct netif * pnetiff = (struct netif *)&xnetif[1];
+#endif
+ printf("[ATWB](_AT_WLAN_AP_STA_ACTIVATE_)\n");
+ if(ap.ssid.val[0] == 0){
+ printf("[ATWB]Error: SSID can't be empty\n");
+ ret = RTW_BADARG;
+ goto exit;
+ }
+ if(ap.channel > 14){
+ printf("[ATWB]Error:bad channel! channel is from 1 to 14\n");
+ ret = RTW_BADARG;
+ goto exit;
+ }
+ if(ap.password == NULL){
+ ap.security_type = RTW_SECURITY_OPEN;
+ }
+ else{
+ ap.security_type = RTW_SECURITY_WPA2_AES_PSK;
+ }
+
+#if CONFIG_WEBSERVER
+ //store into flash
+ memset(wifi_setting.ssid, 0, sizeof(wifi_setting.ssid));;
+ memcpy(wifi_setting.ssid, ap.ssid.val, strlen((char*)ap.ssid.val));
+ wifi_setting.ssid[ap.ssid.len] = '\0';
+ wifi_setting.security_type = ap.security_type;
+ if(ap.security_type !=0)
+ wifi_setting.security_type = 1;
+ else
+ wifi_setting.security_type = 0;
+ if (ap.password)
+ memcpy(wifi_setting.password, ap.password, strlen((char*)ap.password));
+ else
+ memset(wifi_setting.password, 0, sizeof(wifi_setting.password));;
+ wifi_setting.channel = ap.channel;
+#if CONFIG_READ_FLASH
+ StoreApInfo();
+#endif
+#endif
+
+#if CONFIG_LWIP_LAYER
+ dhcps_deinit();
+#endif
+
+ wifi_off();
+ vTaskDelay(20);
+ if ((ret = wifi_on(RTW_MODE_STA_AP)) < 0){
+ printf("ERROR: Wifi on failed!\n");
+ ret = RTW_ERROR;
+ goto exit;
+ }
+
+ printf("Starting AP ...\n");
+ if((ret = wifi_start_ap((char*)ap.ssid.val, ap.security_type, (char*)ap.password, ap.ssid.len, ap.password_len, ap.channel)) < 0) {
+ printf("ERROR: Operation failed!\n");
+ goto exit;
+ }
+ while(1) {
+ char essid[33];
+
+ if(wext_get_ssid(WLAN1_NAME, (unsigned char *) essid) > 0) {
+ if(strcmp((const char *) essid, (const char *)ap.ssid.val) == 0) {
+ printf("%s started\n", ap.ssid.val);
+ ret = RTW_SUCCESS;
+ break;
+ }
+ }
+
+ if(timeout == 0) {
+ printf("ERROR: Start AP timeout!\n");
+ ret = RTW_TIMEOUT;
+ break;
+ }
+
+// vTaskDelay(1 * configTICK_RATE_HZ);
+ vTaskDelay(200/portTICK_RATE_MS);
+ timeout --;
+ }
+#if CONFIG_LWIP_LAYER
+ LwIP_UseStaticIP(&xnetif[1]);
+#ifdef CONFIG_DONT_CARE_TP
+ pnetiff->flags |= NETIF_FLAG_IPSWITCH;
+#endif
+ dhcps_init(pnetiff);
+#endif
+
+exit:
+#if CONFIG_INIC_CMD_RSP
+ inic_c2h_wifi_info("ATWB", ret);
+#endif
+ init_wifi_struct();
+}
+#endif
+
+#ifdef CONFIG_PROMISC
+void fATWM(void *arg){
+ int argc;
+ char *argv[MAX_ARGC] = {0};
+ argv[0] = "wifi_promisc";
+ printf("[ATWM]: _AT_WLAN_PROMISC_\n");
+ if(!arg){
+ printf("[ATWM]Usage: ATWM=DURATION_SECONDS[with_len]\n");
+#if CONFIG_INIC_CMD_RSP
+ inic_c2h_msg("ATWM", RTW_BADARG, NULL, 0);
+#endif
+ return;
+ }
+ if((argc = parse_param(arg, argv)) > 1){
+ cmd_promisc(argc, argv);
+ }
+}
+#endif
+
+#if CONFIG_WEBSERVER
+void fATWE(void *arg){
+ printf("[ATWE]: _AT_WLAN_START_WEB_SERVER_\n");
+ start_web_server();
+}
+#endif
+
+void fATWW(void *arg){
+#if CONFIG_ENABLE_WPS
+ int argc = 0;
+ char *argv[4];
+ printf("[ATWW]: _AT_WLAN_WPS_\n");
+ if(!arg){
+ printf("[ATWW]Usage: ATWW=pbc/pin\n");
+#if CONFIG_INIC_CMD_RSP
+ inic_c2h_msg("ATWW", RTW_BADARG, NULL, 0);
+#endif
+ return;
+ }
+ argv[argc++] = "wifi_wps";
+ argv[argc++] = arg;
+ cmd_wps(argc, argv);
+#else
+ printf("Please set CONFIG_ENABLE_WPS 1 in platform_opts.h to enable ATWW command\n");
+#endif
+}
+void fATWw(void *arg){
+#if defined(CONFIG_ENABLE_WPS_AP) && CONFIG_ENABLE_WPS_AP
+ int argc = 0;
+ char *argv[4];
+ printf("[ATWw]: _AT_WLAN_AP_WPS_\n");
+ if(!arg){
+ printf("[ATWw]Usage: ATWw=pbc/pin\n");
+ return;
+ }
+ argv[argc++] = "wifi_ap_wps";
+ argv[argc++] = arg;
+ cmd_ap_wps(argc, argv);
+#endif
+}
+
+#if CONFIG_ENABLE_P2P
+void fATWG(void *arg){
+ int argc = 0;
+ char *argv[4];
+ printf("[ATWG]: _AT_WLAN_P2P_START_\n");
+ argv[argc++] = "p2p_start";
+ cmd_wifi_p2p_start(argc, argv);
+}
+
+void fATWg(void *arg){
+ int argc = 0;
+ char *argv[4];
+ int ret =0;
+ printf("[ATWg]: _AT_WLAN_P2P_AUTO_GO_START_\n");
+ argv[argc++] = "p2p_auto_go_start";
+ ret = cmd_wifi_p2p_auto_go_start(argc, argv);
+ if(ret < 0)
+ printf("[ATWg]: Nothing to do. Please enter ATWG to initialize P2P.\n");
+}
+
+void fATWH(void *arg){
+ int argc = 0;
+ char *argv[4];
+ printf("[ATWH]: _AT_WLAN_P2P_STOP_\n");
+ argv[argc++] = "p2p_stop";
+ cmd_wifi_p2p_stop(argc, argv);
+}
+void fATWJ(void *arg){
+ int argc = 0;
+ char *argv[4];
+ printf("[ATWJ]: _AT_WLAN_P2P_CONNECT_\n");
+ argv[0] = "p2p_connect";
+ if(!arg){
+ printf("ATWc=[DEST_MAC,pbc/pin]\n");
+ return;
+ }
+ if((argc = parse_param(arg, argv)) > 1){
+ cmd_p2p_connect(argc, argv);
+ }
+}
+void fATWK(void *arg){
+ int argc = 0;
+ char *argv[4];
+ printf("[ATWK]: _AT_WLAN_P2P_DISCONNECT_\n");
+ argv[argc++] = "p2p_disconnect";
+ cmd_p2p_disconnect(argc, argv);
+}
+void fATWN(void *arg){
+ int argc = 0;
+ char *argv[4];
+ printf("[ATWN]: _AT_WLAN_P2P_INFO_\n");
+ argv[argc++] = "p2p_info";
+ cmd_p2p_info(argc, argv);
+}
+void fATWF(void *arg){
+ int argc = 0;
+ char *argv[4];
+ printf("[ATWF]: _AT_WLAN_P2P_FIND_\n");
+ argv[argc++] = "p2p_find";
+ cmd_p2p_find(argc, argv);
+}
+#endif
+#if CONFIG_OTA_UPDATE
+void fATWO(void *arg){
+ int argc = 0;
+ char *argv[MAX_ARGC] = {0};
+ printf("[ATWO]: _AT_WLAN_OTA_UPDATE_\n");
+ if(!arg){
+ printf("[ATWO]Usage: ATWO=IP[PORT] or ATWO= REPOSITORY[FILE_PATH]\n");
+ return;
+ }
+ argv[0] = "update";
+ if((argc = parse_param(arg, argv)) != 3){
+ printf("[ATWO]Usage: ATWO=IP[PORT] or ATWO= REPOSITORY[FILE_PATH]\n");
+ return;
+ }
+ cmd_update(argc, argv);
+}
+#endif
+
+#if CONFIG_AIRKISS
+void fATWX(void *arg)
+{
+ int ret = RTW_SUCCESS;
+
+ rtw_network_info_t wifi;
+ memset(&wifi, 0 , sizeof(rtw_network_info_t));
+
+ ret = airkiss_start(&wifi);
+#if CONFIG_INIC_CMD_RSP
+ if(ret != RTW_SUCCESS)
+ inic_c2h_msg("ATWX", RTW_ERROR, NULL, 0);
+#endif
+}
+#endif
+
+void fATWZ(void *arg){
+ char buf[32] = {0};
+ char *copy = buf;
+ int i = 0;
+ int len = 0;
+ int ret = RTW_SUCCESS;
+
+ printf("[ATWZ]: _AT_WLAN_IWPRIV_\n");
+ if(!arg){
+ printf("[ATWZ]Usage: ATWZ=COMMAND[PARAMETERS]\n");
+ ret = RTW_BADARG;
+ goto exit;
+ }
+ strcpy(copy, arg);
+ len = strlen(copy);
+ do{
+ if((*(copy+i)=='['))
+ *(copy+i)=' ';
+ if((*(copy+i)==']')||(*(copy+i)=='\0')){
+ *(copy+i)='\0';
+ break;
+ }
+ }while((i++) < len);
+
+ i = 0;
+ do{
+ if((*(copy+i)==',')) {
+ *(copy+i)=' ';
+ break;
+ }
+ }while((i++) < len);
+
+#if CONFIG_INIC_CMD_RSP
+ ret = wext_private_command_with_retval(WLAN0_NAME, copy, buf, 32);
+ printf("Private Message: %s\n", (char *) buf);
+ if(ret == RTW_SUCCESS)
+ inic_c2h_msg("ATWZ", ret, buf, strlen(buf));
+#else
+ wext_private_command(WLAN0_NAME, copy, 1);
+#endif
+exit:
+#if CONFIG_INIC_CMD_RSP
+ if(ret != RTW_SUCCESS)
+ inic_c2h_msg("ATWZ", ret, NULL, 0);
+#endif
+ return; // exit label cannot be last statement
+}
+
+#ifdef CONFIG_POWER_SAVING
+void fATXP(void *arg)
+{
+ int argc = 0;
+ char *argv[MAX_ARGC] = {0};
+ int ret = 0;
+ int mode, dtim;
+ int tdma_slot_period, tdma_rfon_period_len_1, tdma_rfon_period_len_2, tdma_rfon_period_len_3;
+#if CONFIG_INIC_CMD_RSP
+ char *res = NULL;
+ int res_len = 0;
+#endif
+
+ printf("[ATXP]: _AT_WLAN_POWER_MODE_\n");
+
+ if (!arg) {
+ printf("[ATXP] Usage: ATXP=lps/ips/dtim/tdma[mode]\n");
+ ret = RTW_BADARG;
+ goto exit;
+ } else {
+ argc = parse_param(arg, argv);
+ if (argc < 3) {
+ printf("[ATXP] Usage: ATXP=lps/ips/dtim/tdma[mode]\n");
+ ret = RTW_BADARG;
+ goto exit;
+ }
+ }
+
+ if (strcmp(argv[1], "lps") == 0) {
+ mode = atoi(argv[2]);
+ if (mode >= 0 && mode < 0xFF) {
+ printf("lps mode:%d\n", mode);
+ wifi_set_power_mode(0xff, mode);
+ }
+ }
+
+ if (strcmp(argv[1], "ips") == 0) {
+ mode = atoi(argv[2]);
+ if (mode >= 0 && mode < 0xFF) {
+ printf("ips mode:%d\n", mode);
+ wifi_set_power_mode(mode, 0xFF);
+ }
+ }
+
+ if (strcmp(argv[1], "tdma") == 0) {
+ if (argc >= 6) {
+ tdma_slot_period = atoi(argv[2]);
+ tdma_rfon_period_len_1 = atoi(argv[3]);
+ tdma_rfon_period_len_2 = atoi(argv[4]);
+ tdma_rfon_period_len_3 = atoi(argv[5]);
+ printf("tdma param: %d %d %d %d\n", tdma_slot_period, tdma_rfon_period_len_1, tdma_rfon_period_len_2, tdma_rfon_period_len_3);
+ wifi_set_tdma_param(tdma_slot_period, tdma_rfon_period_len_1, tdma_rfon_period_len_2, tdma_rfon_period_len_3);
+ }
+ }
+
+ if (strcmp(argv[1], "dtim") == 0) {
+ dtim = atoi(argv[2]);
+ printf("dtim: %d\n", dtim);
+ wifi_set_lps_dtim(dtim);
+ }
+
+ if (strcmp(argv[1], "get") == 0) {
+#if CONFIG_INIC_CMD_RSP
+ char buf[32];
+ int index = 0;
+ memset(buf, 0, sizeof(buf));
+ snprintf(buf, 32, "%s,%s,", argv[1], argv[2]);
+ index = strlen(buf);
+#endif
+ if(strcmp(argv[2], "dtim") == 0){
+ wifi_get_lps_dtim((unsigned char *)&dtim);
+ printf("get dtim: %d\n", (unsigned char)dtim);
+#if CONFIG_INIC_CMD_RSP
+ sprintf(buf+index, "0x%02x", (unsigned char)dtim);
+ res = (char *)buf;
+ res_len = strlen(buf);
+#endif
+ }
+ }
+
+exit:
+#if CONFIG_INIC_CMD_RSP
+ inic_c2h_msg("ATXP", ret, res, res_len);
+ res = NULL;
+ res_len = 0;
+#endif
+ return;
+}
+#endif
+
+void print_wlan_help(void *arg){
+ printf("WLAN AT COMMAND SET:\n==============================\n");
+ printf("1. Wlan Scan for Network Access Point\n");
+ printf(" # ATWS\n");
+ printf("2. Connect to an AES AP\n");
+ printf(" # ATW0=SSID\n");
+ printf(" # ATW1=PASSPHRASE\n");
+ printf(" # ATWC\n");
+ printf("3. Create an AES AP\n");
+ printf(" # ATW3=SSID\n");
+ printf(" # ATW4=PASSPHRASE\n");
+ printf(" # ATW5=CHANNEL\n");
+ printf(" # ATWA\n");
+ printf("4. Ping\n");
+ printf(" # ATWI=xxx.xxx.xxx.xxx\n");
+}
+
+#elif ATCMD_VER == ATVER_2 // UART module at command
+
+// wifi promisc
+// Usage: ATWM=DURATION_SECONDS[with_len]
+#ifdef CONFIG_PROMISC
+void fATWM(void *arg){
+ int argc, error_no = 0;
+ char *argv[MAX_ARGC] = {0};
+ argv[0] = "wifi_promisc";
+ printf("[ATWM]: _AT_WLAN_PROMISC_\n");
+ if(!arg){
+ AT_DBG_MSG(AT_FLAG_WIFI, AT_DBG_ERROR,
+ "[ATWM]Usage: ATWM=DURATION_MSECONDS[with_len]\n");
+#if CONFIG_INIC_CMD_RSP
+ inic_c2h_msg("ATWM", RTW_BADARG, NULL, 0);
+#endif
+ error_no = 1;
+ goto exit;
+ }
+ if((argc = parse_param(arg, argv)) > 1){
+ cmd_promisc(argc, argv);
+ }
+exit:
+ if(error_no==0)
+ at_printf("\r\n[ATWM] OK");
+ else
+ at_printf("\r\n[ATWM] ERROR:%d",error_no);
+ return;
+}
+#endif
+
+//ATPA=,,,[,]
+void fATPA(void *arg)
+{
+ int argc, error_no = 0;
+ char *argv[MAX_ARGC] = {0};
+
+#if CONFIG_LWIP_LAYER
+ struct ip_addr ipaddr;
+ struct ip_addr netmask;
+ struct ip_addr gw;
+ struct netif * pnetif;
+#endif
+ int timeout = 10000/200;
+ unsigned char hidden_ssid = 0;
+ rtw_mode_t wifi_mode_copy;
+
+ if(!arg){
+ AT_DBG_MSG(AT_FLAG_WIFI, AT_DBG_ERROR,
+ "\r\n[ATPA] Usage: ATPA=,,,[,]");
+ error_no = 1;
+ goto exit;
+ }
+
+ argc = parse_param(arg, argv);
+ if(argc < 5){
+ //at_printf("\r\n[ATPA] ERROR : command format error");
+ error_no = 1;
+ goto exit;
+ }
+
+ if( (wifi_mode!=RTW_MODE_AP) && (wifi_mode!=RTW_MODE_STA_AP) ){
+ //at_printf("\r\n[ATPA] ERROR : wifi mode error");
+ error_no = 5;
+ goto exit;
+ }
+ wifi_mode_copy = wifi_mode;
+
+ //SSID
+ if(argv[1] != NULL){
+ ap.ssid.len = strlen((char*)argv[1]);
+ if(ap.ssid.len > 32){
+ //at_printf("\r\n[ATPA] ERROR : SSID length can't exceed 32");
+ error_no = 2;
+ goto exit;
+ }
+ strcpy((char *)ap.ssid.val, (char*)argv[1]);
+ }
+ else{
+ //at_printf("\r\n[ATPA] ERROR : SSID can't be empty");
+ error_no = 2;
+ goto exit;
+ }
+
+ //PASSWORD
+ if(argv[2] != NULL){
+ if( (strlen(argv[2]) < 8) || (strlen(argv[2]) > 64)){
+ //at_printf("\r\n[ATPA] ERROR : PASSWORD length error");
+ error_no = 2;
+ goto exit;
+ }
+ strcpy((char *)password, (char*)argv[2]);
+ ap.password = password;
+ ap.password_len = strlen((char*)argv[2]);
+ ap.security_type = RTW_SECURITY_WPA2_AES_PSK;
+ }
+ else{
+ ap.security_type = RTW_SECURITY_OPEN;
+ }
+
+ //CHANNEL
+ if(argv[3] != NULL){
+ ap.channel = (unsigned char) atoi((const char *)argv[3]);
+ if( (ap.channel < 0) || (ap.channel > 11) ){
+ //at_printf("\r\n[ATPA] ERROR : channel number error");
+ error_no = 2;
+ goto exit;
+ }
+ }
+
+ //HIDDEN SSID
+ if(argv[4] != NULL){
+ if( (atoi(argv[4]) != 0) && (atoi(argv[4]) != 1)){
+ //at_printf("\r\n[ATPA] ERROR : HIDDEN SSID must be 0 or 1");
+ error_no = 2;
+ goto exit;
+ }
+ hidden_ssid = (unsigned char) atoi((const char *)argv[4]);
+ }
+
+ //MAX NUMBER OF STATION
+ if(argv[5] != NULL){
+ unsigned char max_sta = atoi(argv[5]);
+ if(wext_set_sta_num(max_sta) != 0){
+ error_no = 2;
+ goto exit;
+ }
+ }
+
+#if CONFIG_WEBSERVER
+ //store into flash
+ memset(wifi_setting.ssid, 0, sizeof(wifi_setting.ssid));
+ memcpy(wifi_setting.ssid, ap.ssid.val, strlen((char*)ap.ssid.val));
+ wifi_setting.ssid[ap.ssid.len] = '\0';
+ wifi_setting.security_type = ap.security_type;
+ if(ap.security_type !=0)
+ wifi_setting.security_type = 1;
+ else
+ wifi_setting.security_type = 0;
+ if (ap.password)
+ memcpy(wifi_setting.password, ap.password, strlen((char*)ap.password));
+ else
+ memset(wifi_setting.password, 0, sizeof(wifi_setting.password));
+ wifi_setting.channel = ap.channel;
+#if CONFIG_READ_FLASH
+ StoreApInfo();
+#endif
+#endif
+
+#if CONFIG_LWIP_LAYER
+ dhcps_deinit();
+#endif
+ wifi_off();
+ vTaskDelay(20);
+
+ if (wifi_on(wifi_mode_copy) < 0){
+ //at_printf("\r\n[ATPA] ERROR : Wifi on failed");
+ error_no = 3;
+ goto exit;
+ }
+
+ if(wifi_start_ap((char*)ap.ssid.val, ap.security_type, (char*)ap.password, ap.channel, hidden_ssid) < 0) {
+ //at_printf("\r\n[ATPA] ERROR : Start AP failed");
+ error_no = 4;
+ goto exit;
+ }
+
+ while(1) {
+ char essid[33];
+ if(wifi_mode_copy == RTW_MODE_AP ){
+ if(wext_get_ssid( WLAN0_NAME , (unsigned char *) essid) > 0) {
+ if(strcmp((const char *) essid, (const char *)ap.ssid.val) == 0) {
+ break;
+ }
+ }
+ }
+ else if(wifi_mode_copy == RTW_MODE_STA_AP ){
+ if(wext_get_ssid( WLAN1_NAME , (unsigned char *) essid) > 0) {
+ if(strcmp((const char *) essid, (const char *)ap.ssid.val) == 0) {
+ break;
+ }
+ }
+ }
+
+ if(timeout == 0) {
+ //at_printf("\r\n[ATPA] ERROR : Start AP timeout");
+ error_no = 4;
+ break;
+ }
+ vTaskDelay(200/portTICK_RATE_MS);
+// vTaskDelay(1 * configTICK_RATE_HZ);
+ timeout --;
+ }
+#if CONFIG_LWIP_LAYER
+ if(wifi_mode == RTW_MODE_STA_AP)
+ pnetif = &xnetif[1];
+ else
+ pnetif = &xnetif[0];
+
+ LwIP_UseStaticIP(pnetif);
+
+ if(dhcp_mode_ap == 1)
+ dhcps_init(pnetif);
+#endif
+exit:
+ init_wifi_struct();
+
+ if(error_no == 0) {
+#if CONFIG_WLAN_CONNECT_CB
+ extern void connect_start(void);
+ connect_start();
+#endif
+ at_printf("\r\n[ATPA] OK");
+ } else
+ at_printf("\r\n[ATPA] ERROR:%d",error_no);
+
+ return;
+}
+
+/*find ap with "ssid" from scan list*/
+static int _find_ap_from_scan_buf(char*buf, int buflen, char *target_ssid, void *user_data)
+{
+ rtw_wifi_setting_t *pwifi = (rtw_wifi_setting_t *)user_data;
+ int plen = 0;
+
+ while(plen < buflen){
+ u8 len, ssid_len, security_mode;
+ char *ssid;
+
+ // len offset = 0
+ len = (int)*(buf + plen);
+ // check end
+ if(len == 0) break;
+ // ssid offset = 14
+ ssid_len = len - 14;
+ ssid = buf + plen + 14 ;
+ if((ssid_len == strlen(target_ssid))
+ && (!memcmp(ssid, target_ssid, ssid_len)))
+ {
+ strcpy((char*)pwifi->ssid, target_ssid);
+ // channel offset = 13
+ pwifi->channel = *(buf + plen + 13);
+ // security_mode offset = 11
+ security_mode = (u8)*(buf + plen + 11);
+ if(security_mode == IW_ENCODE_ALG_NONE)
+ pwifi->security_type = RTW_SECURITY_OPEN;
+ else if(security_mode == IW_ENCODE_ALG_WEP)
+ pwifi->security_type = RTW_SECURITY_WEP_PSK;
+ else if(security_mode == IW_ENCODE_ALG_CCMP)
+ pwifi->security_type = RTW_SECURITY_WPA2_AES_PSK;
+ break;
+ }
+ plen += len;
+ }
+ return 0;
+}
+
+/*get ap security mode from scan list*/
+static int _get_ap_security_mode(IN char * ssid, OUT rtw_security_t *security_mode, OUT u8 * channel)
+{
+ rtw_wifi_setting_t wifi;
+ u32 scan_buflen = 1000;
+
+ memset(&wifi, 0, sizeof(wifi));
+
+ if(wifi_scan_networks_with_ssid(_find_ap_from_scan_buf, (void*)&wifi, scan_buflen, ssid, strlen(ssid)) != RTW_SUCCESS){
+ printf("Wifi scan failed!\n");
+ return 0;
+ }
+
+ if(strcmp(wifi.ssid, ssid) == 0){
+ *security_mode = wifi.security_type;
+ *channel = wifi.channel;
+ return 1;
+ }
+
+ return 0;
+}
+
+extern u8 key_2char2num(u8 hch, u8 lch);
+
+//ATPN=,,(,)
+void fATPN(void *arg)
+{
+ int argc, error_no = 0;
+ int i,j;
+ char *argv[MAX_ARGC] = {0};
+
+ int mode, ret;
+ unsigned long tick1 = xTaskGetTickCount();
+ unsigned long tick2, tick3;
+ char empty_bssid[6] = {0}, assoc_by_bssid = 0;
+ u8 connect_channel;
+ u8 pscan_config;
+
+ if(!arg){
+ AT_DBG_MSG(AT_FLAG_WIFI, AT_DBG_ERROR,
+ "\r\n[ATPN] Usage : ATPN=,,(,)");
+ error_no = 1;
+ goto exit;
+ }
+
+ argc = parse_param(arg, argv);
+ if( (argc < 2) || (argc > 5) ){
+ //at_printf("\r\n[ATPN] ERROR : command format error");
+ error_no = 1;
+ goto exit;
+ }
+
+ if( (wifi_mode!=RTW_MODE_STA) && (wifi_mode!=RTW_MODE_STA_AP) ){
+ //at_printf("\r\n[ATPN] ERROR : wifi mode error");
+ error_no = 5;
+ goto exit;
+ }
+
+ //SSID
+ if(argv[1] != NULL){
+ strcpy((char *)wifi.ssid.val, (char*)argv[1]);
+ wifi.ssid.len = strlen((char*)argv[1]);
+ }else{
+ //at_printf("\r\n[ATPN] ERROR : SSID can't be Empty");
+ error_no = 2;
+ goto exit;
+ }
+ wifi.security_type = RTW_SECURITY_OPEN;
+
+ //PASSWORD
+ if(argv[2] != NULL){
+ int pwd_len = strlen(argv[2]);
+ if(pwd_len > 64 || (pwd_len < 8 && pwd_len != 5)){
+ //at_printf("\r\n[ATPN] ERROR : PASSWORD format error");
+ error_no = 2;
+ goto exit;
+ }
+ strcpy((char *)password, (char*)argv[2]);
+ wifi.password = password;
+ wifi.password_len = strlen((char*)argv[2]);
+ wifi.security_type = RTW_SECURITY_WPA2_AES_PSK;
+ }
+
+ //KEYID
+ if(argv[3] != NULL){
+ if((strlen((const char *)argv[3]) != 1 ) || (*(char*)argv[3] <'0' ||*(char*)argv[3] >'3')) {
+ //at_printf("\r\n[ATPN] ERROR : Wrong WEP key id. Must be one of 0,1,2, or 3");
+ error_no = 2;
+ goto exit;
+ }
+ wifi.key_id = atoi((const char *)(argv[3]));
+ wifi.security_type = RTW_SECURITY_WEP_PSK;
+ }
+
+ //BSSID
+ if(argv[4] != NULL){
+ if(strlen(argv[4]) != 12){
+ //at_printf("\r\n[ATPN] ERROR : BSSID format error");
+ error_no = 2;
+ goto exit;
+ }
+ for (i=0, j=0; i= 3){
+ printf("Can't get AP security mode and channel.\n");
+ error_no = 6;
+ goto exit;
+ }
+ }
+ if(wifi.security_type == RTW_SECURITY_WEP_PSK || wifi.security_type == RTW_SECURITY_WEP_SHARED)
+ wifi.key_id = (wifi.key_id <0 || wifi.key_id >3)?0:wifi.key_id;
+ }
+ pscan_config = PSCAN_ENABLE;
+ if(connect_channel > 0 && connect_channel < 14)
+ wifi_set_pscan_chan(&connect_channel, &pscan_config, 1);
+#endif
+
+ ret = wifi_connect(
+ wifi.bssid.octet,
+ assoc_by_bssid,
+ (char*)wifi.ssid.val,
+ wifi.security_type,
+ (char*)wifi.password,
+ wifi.key_id,
+ NULL);
+
+ if(ret!= RTW_SUCCESS){
+ //at_printf("\r\n[ATPN] ERROR: Can't connect to AP");
+ error_no = 4;
+ goto exit;
+ }
+
+#if CONFIG_LWIP_LAYER
+ if (dhcp_mode_sta == 2){
+ struct netif * pnetif = &xnetif[0];
+ LwIP_UseStaticIP(pnetif);
+ dhcps_init(pnetif);
+ }
+ else{
+ ret = LwIP_DHCP(0, DHCP_START);
+ if(ret != DHCP_ADDRESS_ASSIGNED)
+ error_no = 7;
+ }
+#endif
+exit:
+ init_wifi_struct();
+ if(error_no == 0) {
+#if CONFIG_WLAN_CONNECT_CB
+ extern void connect_start(void);
+ connect_start();
+#endif
+ at_printf("\r\n[ATPN] OK");
+ } else
+ at_printf("\r\n[ATPN] ERROR:%d",error_no);
+
+ return;
+}
+
+//ATPH=,
+void fATPH(void *arg)
+{
+ int argc, error_no = 0;
+ char *argv[MAX_ARGC] = {0};
+ int mode,enable;
+
+ if(!arg){
+ AT_DBG_MSG(AT_FLAG_WIFI, AT_DBG_ERROR,
+ "\r\n[ATPH] Usage : ATPH=,");
+ error_no = 1;
+ goto exit;
+ }
+
+ argc = parse_param(arg, argv);
+ if(argc != 3){
+ //at_printf("\r\n[ATPH] ERROR : command format error");
+ error_no = 1;
+ goto exit;
+ }
+
+ if(argv[1] != NULL){
+ mode = atoi((const char *)(argv[1]));
+ if(mode != 1 && mode != 2){
+ //at_printf("\r\n[ATPH] ERROR : parameter must be 1 or 2");
+ error_no = 2;
+ goto exit;
+ }
+ }
+
+ if(argv[2] != NULL){
+ enable = atoi((const char *)(argv[2]));
+ if(enable != 1 && enable != 2){
+ //at_printf("\r\n[ATPH] ERROR : parameter must be 1 or 2");
+ error_no = 2;
+ goto exit;
+ }
+ if(mode == 1)
+ dhcp_mode_ap = enable;
+ else if(mode == 2)
+ dhcp_mode_sta = enable;
+ }
+
+exit:
+ if(error_no==0)
+ at_printf("\r\n[ATPH] OK");
+ else
+ at_printf("\r\n[ATPH] ERROR:%d",error_no);
+
+ return;
+
+}
+
+//ATPE=(,,)
+void fATPE(void *arg)
+{
+ int argc, error_no = 0;
+ char *argv[MAX_ARGC] = {0};
+ unsigned int ip_addr = 0;
+ //unsigned char sta_ip[4] = {192,168,3,80}, sta_netmask[4] = {255,255,255,0}, sta_gw[4] = {192,168,3,1};
+
+ if(!arg){
+ AT_DBG_MSG(AT_FLAG_WIFI, AT_DBG_ERROR,
+ "\r\n[ATPE] Usage : ATPE=(,,)");
+ error_no = 1;
+ goto exit;
+ }
+
+ argc = parse_param(arg, argv);
+ if( (argc > 4) || (argc < 2) ){
+ //at_printf("\r\n[ATPE] ERROR : command format error");
+ error_no = 1;
+ goto exit;
+ }
+
+ if(argv[1] != NULL){
+ ip_addr = inet_addr(argv[1]);
+ sta_ip[0] = (unsigned char) ip_addr & 0xff;
+ sta_ip[1] = (unsigned char) (ip_addr >> 8) & 0xff;
+ sta_ip[2] = (unsigned char) (ip_addr >> 16) & 0xff;
+ sta_ip[3] = (unsigned char) (ip_addr >> 24) & 0xff;
+ }
+ else{
+ //at_printf("\r\n[ATPE] ERROR : parameter format error");
+ error_no = 2;
+ goto exit;
+ }
+
+ if(argv[2] != NULL){
+ ip_addr = inet_addr(argv[2]);
+ sta_gw[0] = (unsigned char) ip_addr & 0xff;
+ sta_gw[1] = (unsigned char) (ip_addr >> 8) & 0xff;
+ sta_gw[2] = (unsigned char) (ip_addr >> 16) & 0xff;
+ sta_gw[3] = (unsigned char) (ip_addr >> 24) & 0xff;
+ }
+ else{
+ sta_gw[0] = sta_ip[0];
+ sta_gw[1] = sta_ip[1];
+ sta_gw[2] = sta_ip[2];
+ sta_gw[3] = 1;
+ }
+
+ if(argv[3] != NULL){
+ ip_addr = inet_addr(argv[3]);
+ sta_netmask[0] = (unsigned char) ip_addr & 0xff;
+ sta_netmask[1] = (unsigned char) (ip_addr >> 8) & 0xff;
+ sta_netmask[2] = (unsigned char) (ip_addr >> 16) & 0xff;
+ sta_netmask[3] = (unsigned char) (ip_addr >> 24) & 0xff;
+ }
+ else{
+ sta_netmask[0] = 255;
+ sta_netmask[1] = 255;
+ sta_netmask[2] = 255;
+ sta_netmask[3] = 0;
+ }
+
+exit:
+ if(error_no==0)
+ at_printf("\r\n[ATPE] OK");
+ else
+ at_printf("\r\n[ATPE] ERROR:%d",error_no);
+
+ return;
+
+}
+
+//ATPF=,,
+void fATPF(void *arg)
+{
+ int argc, error_no = 0;
+ char *argv[MAX_ARGC] = {0};
+ unsigned int ip_addr = 0;
+ struct ip_addr start_ip, end_ip;
+
+ if(!arg){
+ AT_DBG_MSG(AT_FLAG_WIFI, AT_DBG_ERROR,
+ "\r\n[ATPF] Usage : ATPF=,,(,,)");
+ error_no = 1;
+ goto exit;
+ }
+
+ argc = parse_param(arg, argv);
+ if( (argc != 4) ){
+ //at_printf("\r\n[ATPF] ERROR : command format error");
+ error_no = 1;
+ goto exit;
+ }
+
+ if(argv[1] != NULL){
+ start_ip.addr = inet_addr(argv[1]);
+ }
+ else{
+ //at_printf("\r\n[ATPF] ERROR : parameter format error");
+ error_no = 2;
+ goto exit;
+ }
+
+ if(argv[2] != NULL){
+ end_ip.addr = inet_addr(argv[2]);
+ }
+ else{
+ //at_printf("\r\n[ATPF] ERROR : parameter format error");
+ error_no = 2;
+ goto exit;
+ }
+
+ dhcps_set_addr_pool(&start_ip,&end_ip);
+
+ if(argv[3] != NULL){
+ ip_addr = inet_addr(argv[3]);
+ ap_ip[0] = (unsigned char) ip_addr & 0xff;
+ ap_ip[1] = (unsigned char) (ip_addr >> 8) & 0xff;
+ ap_ip[2] = (unsigned char) (ip_addr >> 16) & 0xff;
+ ap_ip[3] = (unsigned char) (ip_addr >> 24) & 0xff;
+ }
+ else{
+ //at_printf("\r\n[ATPF] ERROR : parameter format error");
+ error_no = 2;
+ goto exit;
+ }
+
+ ap_gw[0] = ap_ip[0];
+ ap_gw[1] = ap_ip[1];
+ ap_gw[2] = ap_ip[2];
+ ap_gw[3] = ap_ip[3];
+
+ ap_netmask[0] = 255;
+ ap_netmask[1] = 255;
+ ap_netmask[2] = 255;
+ ap_netmask[3] = 0;
+
+exit:
+ if(error_no==0)
+ at_printf("\r\n[ATPF] OK");
+ else
+ at_printf("\r\n[ATPF] ERROR:%d", error_no);
+
+ return;
+}
+
+int atcmd_wifi_read_info_from_flash(u8 *read_data, u32 read_len)
+{
+ atcmd_update_partition_info(AT_PARTITION_WIFI, AT_PARTITION_READ, read_data, read_len);
+ return 0;
+}
+
+void atcmd_wifi_write_info_to_flash(rtw_wifi_setting_t *setting, int enable)
+{
+ struct atcmd_wifi_conf *data_to_flash;
+ rtw_wifi_setting_t *old_setting;
+
+// flash_t flash;
+ u32 channel = 0, i, write_needed = 0;
+ u8 index = 0;
+ u32 data;
+
+ data_to_flash = (struct atcmd_wifi_conf *)malloc(sizeof(struct atcmd_wifi_conf));
+
+ if(data_to_flash) {
+ if(enable){
+ memset((u8 *)data_to_flash, 0, sizeof(struct atcmd_wifi_conf));
+ atcmd_update_partition_info(AT_PARTITION_WIFI, AT_PARTITION_READ, (u8 *)data_to_flash, sizeof(struct atcmd_wifi_conf));
+ old_setting = &(data_to_flash->setting);
+ if(memcmp((u8 *)old_setting, setting, sizeof(rtw_wifi_setting_t))){
+ memcpy(old_setting, setting, sizeof(rtw_wifi_setting_t));
+ write_needed = 1;
+ }
+ if(setting->mode == RTW_MODE_STA || setting->mode == RTW_MODE_STA_AP){
+ struct wlan_fast_reconnect reconn;
+ int found = 0;
+ /*clean wifi ssid,key and bssid*/
+ memset((u8 *)&reconn, 0, sizeof(struct wlan_fast_reconnect));
+
+ channel = setting->channel;
+
+ memset(psk_essid[index], 0, sizeof(psk_essid[index]));
+ strncpy(psk_essid[index], setting->ssid, strlen(setting->ssid));
+ switch(setting->security_type){
+ case RTW_SECURITY_OPEN:
+ memset(psk_passphrase[index], 0, sizeof(psk_passphrase[index]));
+ memset(wpa_global_PSK[index], 0, sizeof(wpa_global_PSK[index]));
+ reconn.security_type = RTW_SECURITY_OPEN;
+ break;
+ case RTW_SECURITY_WEP_PSK:
+ channel |= (setting->key_idx) << 28;
+ memset(psk_passphrase[index], 0, sizeof(psk_passphrase[index]));
+ memset(wpa_global_PSK[index], 0, sizeof(wpa_global_PSK[index]));
+ memcpy(psk_passphrase[index], setting->password, sizeof(psk_passphrase[index]));
+ reconn.security_type = RTW_SECURITY_WEP_PSK;
+ break;
+ case RTW_SECURITY_WPA_TKIP_PSK:
+ reconn.security_type = RTW_SECURITY_WPA_TKIP_PSK;
+ break;
+ case RTW_SECURITY_WPA2_AES_PSK:
+ reconn.security_type = RTW_SECURITY_WPA2_AES_PSK;
+ break;
+ default:
+ break;
+ }
+
+ memcpy(reconn.psk_essid, psk_essid[index], sizeof(reconn.psk_essid));
+ if (strlen(psk_passphrase64) == 64) {
+ memcpy(reconn.psk_passphrase, psk_passphrase64, sizeof(reconn.psk_passphrase));
+ } else {
+ memcpy(reconn.psk_passphrase, psk_passphrase[index], sizeof(reconn.psk_passphrase));
+ }
+ memcpy(reconn.wpa_global_PSK, wpa_global_PSK[index], sizeof(reconn.wpa_global_PSK));
+ memcpy(&(reconn.channel), &channel, 4);
+
+ if(data_to_flash->reconn_num < 0 || data_to_flash->reconn_num > ATCMD_WIFI_CONN_STORE_MAX_NUM ||
+ data_to_flash->reconn_last_index < 0 || data_to_flash->reconn_last_index > ATCMD_WIFI_CONN_STORE_MAX_NUM
+ ){
+ data_to_flash->reconn_num = 0;
+ data_to_flash->reconn_last_index = -1;
+ }
+
+ reconn.enable = enable;
+ for(i = 0; i < data_to_flash->reconn_num; i++){
+ if(memcmp((u8 *)&reconn, (u8 *)&(data_to_flash->reconn[i]), sizeof(struct wlan_fast_reconnect)) == 0) {
+ AT_DBG_MSG(AT_FLAG_WIFI, AT_DBG_ALWAYS,
+ "the same profile found in flash");
+ found = 1;
+ break;
+ }
+ }
+ if(!found){
+ data_to_flash->reconn_last_index++;
+ if(data_to_flash->reconn_last_index >= ATCMD_WIFI_CONN_STORE_MAX_NUM)
+ data_to_flash->reconn_last_index -= ATCMD_WIFI_CONN_STORE_MAX_NUM;
+ memcpy((u8 *)&data_to_flash->reconn[data_to_flash->reconn_last_index], (u8 *)&reconn, sizeof(struct wlan_fast_reconnect));
+ data_to_flash->reconn_num++;
+ if(data_to_flash->reconn_num > ATCMD_WIFI_CONN_STORE_MAX_NUM)
+ data_to_flash->reconn_num = ATCMD_WIFI_CONN_STORE_MAX_NUM;
+ write_needed = 1;
+ }
+ }
+ if(write_needed || data_to_flash->auto_enable != enable){
+ data_to_flash->auto_enable = enable;
+ atcmd_update_partition_info(AT_PARTITION_WIFI, AT_PARTITION_WRITE, (u8 *)data_to_flash, sizeof(struct atcmd_wifi_conf));
+ }
+ }else{
+ atcmd_update_partition_info(AT_PARTITION_WIFI, AT_PARTITION_ERASE, (u8 *)data_to_flash, sizeof(struct atcmd_wifi_conf));
+ }
+ }
+ if(data_to_flash) {
+ free(data_to_flash);
+ }
+}
+
+int atcmd_wifi_restore_from_flash(void)
+{
+// flash_t flash;
+ struct atcmd_wifi_conf *data;
+ rtw_wifi_setting_t *setting;
+ struct wlan_fast_reconnect *reconn;
+ uint32_t channel;
+ uint32_t security_type;
+ uint8_t pscan_config;
+ char key_id[2] = {0};
+ int ret = -1, i;
+ int mode;
+ rtw_network_info_t wifi = {
+ {0}, // ssid
+ {0}, // bssid
+ 0, // security
+ NULL, // password
+ 0, // password len
+ -1 // key id
+ };
+ data = (struct atcmd_wifi_conf *)rtw_zmalloc(sizeof(struct atcmd_wifi_conf));
+ if(data){
+ atcmd_update_partition_info(AT_PARTITION_WIFI, AT_PARTITION_READ, (u8 *)data, sizeof(struct atcmd_wifi_conf));
+ if(data->auto_enable != 1)
+ goto exit;
+ setting = &data->setting;
+ if(setting->mode == RTW_MODE_AP || setting->mode == RTW_MODE_STA_AP){
+ //start AP here
+ goto exit;
+ }
+
+ //Check if in AP mode
+ wext_get_mode(WLAN0_NAME, &mode);
+ if(mode == IW_MODE_MASTER) {
+#if CONFIG_LWIP_LAYER
+ dhcps_deinit();
+#endif
+ wifi_off();
+ vTaskDelay(20);
+ if (wifi_on(RTW_MODE_STA) < 0){
+ printf("ERROR: Wifi on failed!\n");
+ ret = -1;
+ goto exit;
+ }
+ }
+
+#if CONFIG_AUTO_RECONNECT
+ //setup reconnection flag
+ wifi_set_autoreconnect(0);
+#endif
+ int last_index = data->reconn_last_index;
+ for(i = 0; i < data->reconn_num; i++){
+ reconn = &data->reconn[last_index];
+ last_index ++;
+ if(last_index >= ATCMD_WIFI_CONN_STORE_MAX_NUM)
+ last_index -= ATCMD_WIFI_CONN_STORE_MAX_NUM;
+ if(reconn->enable != 1){
+ continue;
+ }
+ memcpy(psk_essid, reconn->psk_essid, sizeof(reconn->psk_essid));
+ memcpy(psk_passphrase, reconn->psk_passphrase, sizeof(reconn->psk_passphrase));
+ memcpy(wpa_global_PSK, reconn->wpa_global_PSK, sizeof(reconn->wpa_global_PSK));
+ channel = reconn->channel;
+ sprintf(key_id,"%d",(char) (channel>>28));
+ channel &= 0xff;
+ security_type = reconn->security_type;
+ pscan_config = PSCAN_ENABLE | PSCAN_FAST_SURVEY;
+ //set partial scan for entering to listen beacon quickly
+ wifi_set_pscan_chan((uint8_t *)&channel, &pscan_config, 1);
+
+ wifi.security_type = security_type;
+ //SSID
+ strcpy((char *)wifi.ssid.val, (char*)psk_essid);
+ wifi.ssid.len = strlen((char*)psk_essid);
+
+ switch(security_type){
+ case RTW_SECURITY_WEP_PSK:
+ wifi.password = (unsigned char*) psk_passphrase;
+ wifi.password_len = strlen((char*)psk_passphrase);
+ wifi.key_id = atoi((const char *)key_id);
+ break;
+ case RTW_SECURITY_WPA_TKIP_PSK:
+ case RTW_SECURITY_WPA2_AES_PSK:
+ wifi.password = (unsigned char*) psk_passphrase;
+ wifi.password_len = strlen((char*)psk_passphrase);
+ break;
+ default:
+ break;
+ }
+
+ ret = wifi_connect(
+ NULL,
+ 0,
+ (char*)wifi.ssid.val,
+ wifi.security_type,
+ (char*)wifi.password,
+ wifi.key_id,
+ NULL);
+ if(ret == RTW_SUCCESS){
+ LwIP_DHCP(0, DHCP_START);
+ ret = 0;
+#if CONFIG_WLAN_CONNECT_CB
+ extern void connect_start(void);
+ connect_start();
+#endif
+ break;
+ }
+ }
+ }
+
+exit:
+ if(data)
+ rtw_mfree((u8 *)data, sizeof(struct wlan_fast_reconnect));
+ return ret;
+}
+
+//ATPG=
+void fATPG(void *arg)
+{
+ int argc, error_no = 0;
+ char *argv[MAX_ARGC] = {0};
+// flash_t flash;
+// struct wlan_fast_reconnect read_data = {0};
+
+ if(!arg){
+ AT_DBG_MSG(AT_FLAG_WIFI, AT_DBG_ERROR,
+ "[ATPG] Usage : ATPG=\r\n");
+ error_no = 1;
+ goto exit;
+ }
+ argc = parse_param(arg, argv);
+ if(argc != 2){
+ //at_printf("\r\n[ATPG] ERROR : command format error");
+ error_no = 1;
+ goto exit;
+ }
+
+ //ENABLE FAST CONNECT
+ if(argv[1] != NULL){
+#if 0
+ device_mutex_lock(RT_DEV_LOCK_FLASH);
+ flash_stream_read(&flash, FAST_RECONNECT_DATA, sizeof(struct wlan_fast_reconnect), (u8 *) &read_data);
+ read_data.enable = atoi((const char *)(argv[1]));
+ if(read_data.enable != 0 && read_data.enable != 1){
+ //at_printf("\r\n[ATPG] ERROR : parameter must be 0 or 1");
+ error_no = 2;
+ device_mutex_unlock(RT_DEV_LOCK_FLASH);
+ goto exit;
+ }
+ flash_erase_sector(&flash, FAST_RECONNECT_DATA);
+ flash_stream_write(&flash, FAST_RECONNECT_DATA, sizeof(struct wlan_fast_reconnect), (u8 *) &read_data);
+ device_mutex_unlock(RT_DEV_LOCK_FLASH);
+#else
+ rtw_wifi_setting_t setting;
+ int enable = atoi((const char *)(argv[1]));
+ if(enable != 0 && enable != 1){
+ error_no = 2;
+ goto exit;
+ }
+ if(enable == 1){
+ u8 *ifname[1] = {WLAN0_NAME};
+ if(wifi_get_setting((const char*)ifname[0],&setting)){
+ AT_DBG_MSG(AT_FLAG_WIFI, AT_DBG_ERROR,
+ "wifi_get_setting fail");
+ error_no = 3;
+ goto exit;
+ }
+ }
+ atcmd_wifi_write_info_to_flash(&setting, enable);
+#endif
+ }
+
+exit:
+ if(error_no==0)
+ at_printf("\r\n[ATPG] OK");
+ else
+ at_printf("\r\n[ATPG] ERROR:%d",error_no);
+
+ return;
+}
+
+// set MAC address
+//ATPM=