From 76247cfc7a9df9d8851ffb34b1256fb0b6b08760 Mon Sep 17 00:00:00 2001 From: polyfractal Date: Tue, 10 Jan 2017 06:42:22 -0500 Subject: [PATCH] Fix overly-enthusiastic .gitignore --- .gitignore | 2 +- .../Curve25519/rom_wac_curve25519-donna.h | 66 + .../External/GladmanAES/rom_wac_aes.h | 220 ++ .../External/GladmanAES/rom_wac_brg_types.h | 229 ++ .../common/application/google/google_nest.h | 23 + .../jd_joinlink/example_joinlink.c | 675 +++++ .../common/application/jd_joinlink/joinlink.c | 1100 ++++++++ .../common/application/jd_joinlink/joinlink.h | 64 + .../application/uart_adapter/uart_adapter.c | 2225 +++++++++++++++++ .../application/uart_adapter/uart_adapter.h | 264 ++ .../common/application/wigadget/cloud_link.c | 82 + .../common/application/wigadget/cloud_link.h | 11 + component/common/application/wigadget/shtc1.c | 185 ++ component/common/application/wigadget/shtc1.h | 13 + .../common/application/wigadget/wigadget.c | 727 ++++++ .../common/application/wigadget/wigadget.h | 11 + .../application/xmodem/uart_fw_update.c | 1073 ++++++++ component/common/application/xmodem/xmodem.h | 86 + .../application/xmodem/xmport_loguart.h | 25 + .../common/application/xmodem/xmport_uart.h | 24 + 20 files changed, 7104 insertions(+), 1 deletion(-) create mode 100644 component/common/application/apple/WACServer/External/Curve25519/rom_wac_curve25519-donna.h create mode 100644 component/common/application/apple/WACServer/External/GladmanAES/rom_wac_aes.h create mode 100644 component/common/application/apple/WACServer/External/GladmanAES/rom_wac_brg_types.h create mode 100644 component/common/application/google/google_nest.h create mode 100644 component/common/application/jd_joinlink/example_joinlink.c create mode 100644 component/common/application/jd_joinlink/joinlink.c create mode 100644 component/common/application/jd_joinlink/joinlink.h create mode 100644 component/common/application/uart_adapter/uart_adapter.c create mode 100644 component/common/application/uart_adapter/uart_adapter.h create mode 100644 component/common/application/wigadget/cloud_link.c create mode 100644 component/common/application/wigadget/cloud_link.h create mode 100644 component/common/application/wigadget/shtc1.c create mode 100644 component/common/application/wigadget/shtc1.h create mode 100644 component/common/application/wigadget/wigadget.c create mode 100644 component/common/application/wigadget/wigadget.h create mode 100644 component/common/application/xmodem/uart_fw_update.c create mode 100644 component/common/application/xmodem/xmodem.h create mode 100644 component/common/application/xmodem/xmport_loguart.h create mode 100644 component/common/application/xmodem/xmport_uart.h diff --git a/.gitignore b/.gitignore index 55f626e..f0bbec1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ target Cargo.lock -application +./application/ *.o src/c/inc/build_info.h diff --git a/component/common/application/apple/WACServer/External/Curve25519/rom_wac_curve25519-donna.h b/component/common/application/apple/WACServer/External/Curve25519/rom_wac_curve25519-donna.h new file mode 100644 index 0000000..41dabb1 --- /dev/null +++ b/component/common/application/apple/WACServer/External/Curve25519/rom_wac_curve25519-donna.h @@ -0,0 +1,66 @@ +/* + File: curve25519-donna.h + Package: WACServer + Version: WACServer-1.14 + + Disclaimer: IMPORTANT: This Apple software is supplied to you, by Apple Inc. ("Apple"), in your + capacity as a current, and in good standing, Licensee in the MFi Licensing Program. Use of this + Apple software is governed by and subject to the terms and conditions of your MFi License, + including, but not limited to, the restrictions specified in the provision entitled ”Public + Software”, and is further subject to your agreement to the following additional terms, and your + agreement that the use, installation, modification or redistribution of this Apple software + constitutes acceptance of these additional terms. If you do not agree with these additional terms, + please do not use, install, modify or redistribute this Apple software. + + Subject to all of these terms and in consideration of your agreement to abide by them, Apple grants + you, for as long as you are a current and in good-standing MFi Licensee, a personal, non-exclusive + license, under Apple's copyrights in this original Apple software (the "Apple Software"), to use, + reproduce, and modify the Apple Software in source form, and to use, reproduce, modify, and + redistribute the Apple Software, with or without modifications, in binary form. While you may not + redistribute the Apple Software in source form, should you redistribute the Apple Software in binary + form, you must retain this notice and the following text and disclaimers in all such redistributions + of the Apple Software. Neither the name, trademarks, service marks, or logos of Apple Inc. may be + used to endorse or promote products derived from the Apple Software without specific prior written + permission from Apple. Except as expressly stated in this notice, no other rights or licenses, + express or implied, are granted by Apple herein, including but not limited to any patent rights that + may be infringed by your derivative works or by other works in which the Apple Software may be + incorporated. + + Unless you explicitly state otherwise, if you provide any ideas, suggestions, recommendations, bug + fixes or enhancements to Apple in connection with this software (“Feedback”), you hereby grant to + Apple a non-exclusive, fully paid-up, perpetual, irrevocable, worldwide license to make, use, + reproduce, incorporate, modify, display, perform, sell, make or have made derivative works of, + distribute (directly or indirectly) and sublicense, such Feedback in connection with Apple products + and services. Providing this Feedback is voluntary, but if you do provide Feedback to Apple, you + acknowledge and agree that Apple may exercise the license granted above without the payment of + royalties or further consideration to Participant. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR + IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR + IN COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION + AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT + (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Copyright (C) 2009 Apple Inc. All Rights Reserved. +*/ + +#ifndef __curve25519_donnaDotH__ +#define __curve25519_donnaDotH__ + +#ifdef __cplusplus + extern "C" { +#endif + +void curve25519_donna( unsigned char *outKey, const unsigned char *inSecret, const unsigned char *inBasePoint ); + +#ifdef __cplusplus + } +#endif + +#endif // __curve25519_donnaDotH__ diff --git a/component/common/application/apple/WACServer/External/GladmanAES/rom_wac_aes.h b/component/common/application/apple/WACServer/External/GladmanAES/rom_wac_aes.h new file mode 100644 index 0000000..0384f55 --- /dev/null +++ b/component/common/application/apple/WACServer/External/GladmanAES/rom_wac_aes.h @@ -0,0 +1,220 @@ +/* +--------------------------------------------------------------------------- +Copyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved. + +The redistribution and use of this software (with or without changes) +is allowed without the payment of fees or royalties provided that: + + source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation. + +This software is provided 'as is' with no explicit or implied warranties +in respect of its operation, including, but not limited to, correctness +and fitness for purpose. +--------------------------------------------------------------------------- +Issue Date: 20/12/2007 + + This file contains the definitions required to use AES in C. See aesopt.h + for optimisation details. +*/ + +#ifndef _AES_H +#define _AES_H + +#include + +/* This include is used to find 8 & 32 bit unsigned integer types */ +#include "rom_wac_brg_types.h" + +/* Use AES encrypt/decrypt in wlan ROM codes */ +#include "rom_aes.h" +extern int aes_set_key( aes_context *ctx, u8 *key, int nbits ); + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#define AES_128 /* if a fast 128 bit key scheduler is needed */ +#define AES_192 /* if a fast 192 bit key scheduler is needed */ +#define AES_256 /* if a fast 256 bit key scheduler is needed */ +#define AES_VAR /* if variable key size scheduler is needed */ +#define AES_MODES /* if support is needed for modes */ + +/* The following must also be set in assembler files if being used */ + +#define AES_ENCRYPT /* if support for encryption is needed */ +#define AES_DECRYPT /* if support for decryption is needed */ +#define AES_REV_DKS /* define to reverse decryption key schedule */ + +#define AES_BLOCK_SIZE 16 /* the AES block size in bytes */ +#define N_COLS 4 /* the number of columns in the state */ + +/* The key schedule length is 11, 13 or 15 16-byte blocks for 128, */ +/* 192 or 256-bit keys respectively. That is 176, 208 or 240 bytes */ +/* or 44, 52 or 60 32-bit words. */ + +#if defined( AES_VAR ) || defined( AES_256 ) +#define KS_LENGTH 60 +#elif defined( AES_192 ) +#define KS_LENGTH 52 +#else +#define KS_LENGTH 44 +#endif + +#define AES_RETURN INT_RETURN + +/* the character array 'inf' in the following structures is used */ +/* to hold AES context information. This AES code uses cx->inf.b[0] */ +/* to hold the number of rounds multiplied by 16. The other three */ +/* elements can be used by code that implements additional modes */ + +typedef union +{ uint_32t l; + uint_8t b[4]; +} aes_inf; + +typedef struct +{ +#if 0 + uint_32t ks[KS_LENGTH]; +#else + aes_context ctx; +#endif + aes_inf inf; +} aes_encrypt_ctx; + +typedef struct +{ +#if 0 + uint_32t ks[KS_LENGTH]; +#else + aes_context ctx; +#endif + aes_inf inf; +} aes_decrypt_ctx; + +/* This routine must be called before first use if non-static */ +/* tables are being used */ + +AES_RETURN aes_init(void); + +/* Key lengths in the range 16 <= key_len <= 32 are given in bytes, */ +/* those in the range 128 <= key_len <= 256 are given in bits */ + +#if defined( AES_ENCRYPT ) + +#if defined( AES_128 ) || defined( AES_VAR) +AES_RETURN aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1]); +#endif + +#if defined( AES_192 ) || defined( AES_VAR) +AES_RETURN aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1]); +#endif + +#if defined( AES_256 ) || defined( AES_VAR) +AES_RETURN aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1]); +#endif + +#if defined( AES_VAR ) +AES_RETURN aes_encrypt_key(const unsigned char *key, int key_len, aes_encrypt_ctx cx[1]); +#endif + +#if 0 +AES_RETURN aes_encrypt(const unsigned char *in, unsigned char *out, const aes_encrypt_ctx cx[1]); +#else +extern void aes_encrypt( aes_context *ctx, u8 input[16], u8 output[16] ); +#endif + +#endif + +#if defined( AES_DECRYPT ) + +#if defined( AES_128 ) || defined( AES_VAR) +AES_RETURN aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1]); +#endif + +#if defined( AES_192 ) || defined( AES_VAR) +AES_RETURN aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1]); +#endif + +#if defined( AES_256 ) || defined( AES_VAR) +AES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1]); +#endif + +#if defined( AES_VAR ) +AES_RETURN aes_decrypt_key(const unsigned char *key, int key_len, aes_decrypt_ctx cx[1]); +#endif + +#if 0 +AES_RETURN aes_decrypt(const unsigned char *in, unsigned char *out, const aes_decrypt_ctx cx[1]); +#else +extern void aes_decrypt( aes_context *ctx, u8 input[16], u8 output[16] ); +#endif + +#endif + +#if defined( AES_MODES ) + +/* Multiple calls to the following subroutines for multiple block */ +/* ECB, CBC, CFB, OFB and CTR mode encryption can be used to handle */ +/* long messages incremantally provided that the context AND the iv */ +/* are preserved between all such calls. For the ECB and CBC modes */ +/* each individual call within a series of incremental calls must */ +/* process only full blocks (i.e. len must be a multiple of 16) but */ +/* the CFB, OFB and CTR mode calls can handle multiple incremental */ +/* calls of any length. Each mode is reset when a new AES key is */ +/* set but ECB and CBC operations can be reset without setting a */ +/* new key by setting a new IV value. To reset CFB, OFB and CTR */ +/* without setting the key, aes_mode_reset() must be called and the */ +/* IV must be set. NOTE: All these calls update the IV on exit so */ +/* this has to be reset if a new operation with the same IV as the */ +/* previous one is required (or decryption follows encryption with */ +/* the same IV array). */ + +AES_RETURN aes_test_alignment_detection(unsigned int n); + +AES_RETURN aes_ecb_encrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, const aes_encrypt_ctx cx[1]); + +AES_RETURN aes_ecb_decrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, const aes_decrypt_ctx cx[1]); + +AES_RETURN aes_cbc_encrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *iv, const aes_encrypt_ctx cx[1]); + +AES_RETURN aes_cbc_decrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *iv, const aes_decrypt_ctx cx[1]); + +AES_RETURN aes_mode_reset(aes_encrypt_ctx cx[1]); + +AES_RETURN aes_cfb_encrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *iv, aes_encrypt_ctx cx[1]); + +AES_RETURN aes_cfb_decrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *iv, aes_encrypt_ctx cx[1]); + +#define aes_ofb_encrypt aes_ofb_crypt +#define aes_ofb_decrypt aes_ofb_crypt + +AES_RETURN aes_ofb_crypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *iv, aes_encrypt_ctx cx[1]); + +typedef void cbuf_inc(unsigned char *cbuf); + +#define aes_ctr_encrypt aes_ctr_crypt +#define aes_ctr_decrypt aes_ctr_crypt + +AES_RETURN aes_ctr_crypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *cbuf, cbuf_inc ctr_inc, aes_encrypt_ctx cx[1]); + +#endif + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/component/common/application/apple/WACServer/External/GladmanAES/rom_wac_brg_types.h b/component/common/application/apple/WACServer/External/GladmanAES/rom_wac_brg_types.h new file mode 100644 index 0000000..a7f6d1d --- /dev/null +++ b/component/common/application/apple/WACServer/External/GladmanAES/rom_wac_brg_types.h @@ -0,0 +1,229 @@ +/* +--------------------------------------------------------------------------- +Copyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved. + +The redistribution and use of this software (with or without changes) +is allowed without the payment of fees or royalties provided that: + + source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation. + +This software is provided 'as is' with no explicit or implied warranties +in respect of its operation, including, but not limited to, correctness +and fitness for purpose. +--------------------------------------------------------------------------- +Issue Date: 20/12/2007 + + The unsigned integer types defined here are of the form uint_t where + is the length of the type; for example, the unsigned 32-bit type is + 'uint_32t'. These are NOT the same as the 'C99 integer types' that are + defined in the inttypes.h and stdint.h headers since attempts to use these + types have shown that support for them is still highly variable. However, + since the latter are of the form uint_t, a regular expression search + and replace (in VC++ search on 'uint_{:z}t' and replace with 'uint\1_t') + can be used to convert the types used here to the C99 standard types. +*/ + +#ifndef _BRG_TYPES_H +#define _BRG_TYPES_H + +#if defined(__cplusplus) +extern "C" { +#endif + +#include +#if 0 +#if defined( _MSC_VER ) && ( _MSC_VER >= 1300 ) +# include +# define ptrint_t intptr_t +#elif defined( __ECOS__ ) +# define intptr_t unsigned int +# define ptrint_t intptr_t +#elif defined( __GNUC__ ) && ( __GNUC__ >= 3 ) +# include +# define ptrint_t intptr_t +#else +# define ptrint_t int +#endif +#else +# include +# define ptrint_t intptr_t +#ifndef u8 + typedef uint8_t u8; +#endif +#ifndef u32 + typedef uint32_t u32; +#endif +#endif + +#ifndef BRG_UI8 +# define BRG_UI8 +# if UCHAR_MAX == 255u + typedef unsigned char uint_8t; +# else +# error Please define uint_8t as an 8-bit unsigned integer type in brg_types.h +# endif +#endif + +#ifndef BRG_UI16 +# define BRG_UI16 +# if USHRT_MAX == 65535u + typedef unsigned short uint_16t; +# else +# error Please define uint_16t as a 16-bit unsigned short type in brg_types.h +# endif +#endif + +#ifndef BRG_UI32 +# define BRG_UI32 +# if UINT_MAX == 4294967295u +# define li_32(h) 0x##h##u + typedef unsigned int uint_32t; +# elif ULONG_MAX == 4294967295u +# define li_32(h) 0x##h##ul + typedef unsigned long uint_32t; +# elif defined( _CRAY ) +# error This code needs 32-bit data types, which Cray machines do not provide +# else +# error Please define uint_32t as a 32-bit unsigned integer type in brg_types.h +# endif +#endif + +#ifndef BRG_UI64 +# if defined( __BORLANDC__ ) && !defined( __MSDOS__ ) +# define BRG_UI64 +# define li_64(h) 0x##h##ui64 + typedef unsigned __int64 uint_64t; +# elif defined( _MSC_VER ) && ( _MSC_VER < 1300 ) /* 1300 == VC++ 7.0 */ +# define BRG_UI64 +# define li_64(h) 0x##h##ui64 + typedef unsigned __int64 uint_64t; +# elif defined( __sun ) && defined( ULONG_MAX ) && ULONG_MAX == 0xfffffffful +# define BRG_UI64 +# define li_64(h) 0x##h##ull + typedef unsigned long long uint_64t; +# elif defined( __MVS__ ) +# define BRG_UI64 +# define li_64(h) 0x##h##ull + typedef unsigned int long long uint_64t; +# elif defined( UINT_MAX ) && UINT_MAX > 4294967295u +# if UINT_MAX == 18446744073709551615u +# define BRG_UI64 +# define li_64(h) 0x##h##u + typedef unsigned int uint_64t; +# endif +# elif defined( ULONG_MAX ) && ULONG_MAX > 4294967295u +# if ULONG_MAX == 18446744073709551615ul +# define BRG_UI64 +# define li_64(h) 0x##h##ul + typedef unsigned long uint_64t; +# endif +# elif defined( ULLONG_MAX ) && ULLONG_MAX > 4294967295u +# if ULLONG_MAX == 18446744073709551615ull +# define BRG_UI64 +# define li_64(h) 0x##h##ull + typedef unsigned long long uint_64t; +# endif +# elif defined( ULONG_LONG_MAX ) && ULONG_LONG_MAX > 4294967295u +# if ULONG_LONG_MAX == 18446744073709551615ull +# define BRG_UI64 +# define li_64(h) 0x##h##ull + typedef unsigned long long uint_64t; +# endif +# endif +#endif + +#if !defined( BRG_UI64 ) +# if defined( NEED_UINT_64T ) +# error Please define uint_64t as an unsigned 64 bit type in brg_types.h +# endif +#endif + +#ifndef RETURN_VALUES +# define RETURN_VALUES +# if defined( DLL_EXPORT ) +# if defined( _MSC_VER ) || defined ( __INTEL_COMPILER ) +# define VOID_RETURN __declspec( dllexport ) void __stdcall +# define INT_RETURN __declspec( dllexport ) int __stdcall +# elif defined( __GNUC__ ) +# define VOID_RETURN __declspec( __dllexport__ ) void +# define INT_RETURN __declspec( __dllexport__ ) int +# else +# error Use of the DLL is only available on the Microsoft, Intel and GCC compilers +# endif +# elif defined( DLL_IMPORT ) +# if defined( _MSC_VER ) || defined ( __INTEL_COMPILER ) +# define VOID_RETURN __declspec( dllimport ) void __stdcall +# define INT_RETURN __declspec( dllimport ) int __stdcall +# elif defined( __GNUC__ ) +# define VOID_RETURN __declspec( __dllimport__ ) void +# define INT_RETURN __declspec( __dllimport__ ) int +# else +# error Use of the DLL is only available on the Microsoft, Intel and GCC compilers +# endif +# elif defined( __WATCOMC__ ) +# define VOID_RETURN void __cdecl +# define INT_RETURN int __cdecl +# else +# define VOID_RETURN void +# define INT_RETURN int +# endif +#endif + +/* These defines are used to detect and set the memory alignment of pointers. + Note that offsets are in bytes. + + ALIGN_OFFSET(x,n) return the positive or zero offset of + the memory addressed by the pointer 'x' + from an address that is aligned on an + 'n' byte boundary ('n' is a power of 2) + + ALIGN_FLOOR(x,n) return a pointer that points to memory + that is aligned on an 'n' byte boundary + and is not higher than the memory address + pointed to by 'x' ('n' is a power of 2) + + ALIGN_CEIL(x,n) return a pointer that points to memory + that is aligned on an 'n' byte boundary + and is not lower than the memory address + pointed to by 'x' ('n' is a power of 2) +*/ + +#define ALIGN_OFFSET(x,n) (((ptrint_t)(x)) & ((n) - 1)) +#define ALIGN_FLOOR(x,n) ((uint_8t*)(x) - ( ((ptrint_t)(x)) & ((n) - 1))) +#define ALIGN_CEIL(x,n) ((uint_8t*)(x) + (-((ptrint_t)(x)) & ((n) - 1))) + +/* These defines are used to declare buffers in a way that allows + faster operations on longer variables to be used. In all these + defines 'size' must be a power of 2 and >= 8. NOTE that the + buffer size is in bytes but the type length is in bits + + UNIT_TYPEDEF(x,size) declares a variable 'x' of length + 'size' bits + + BUFR_TYPEDEF(x,size,bsize) declares a buffer 'x' of length 'bsize' + bytes defined as an array of variables + each of 'size' bits (bsize must be a + multiple of size / 8) + + UNIT_CAST(x,size) casts a variable to a type of + length 'size' bits + + UPTR_CAST(x,size) casts a pointer to a pointer to a + varaiable of length 'size' bits +*/ + +#define UI_TYPE(size) uint_##size##t +#define UNIT_TYPEDEF(x,size) typedef UI_TYPE(size) x +#define BUFR_TYPEDEF(x,size,bsize) typedef UI_TYPE(size) x[bsize / (size >> 3)] +#define UNIT_CAST(x,size) ((UI_TYPE(size) )(x)) +#define UPTR_CAST(x,size) ((UI_TYPE(size)*)(x)) + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/component/common/application/google/google_nest.h b/component/common/application/google/google_nest.h new file mode 100644 index 0000000..bd46678 --- /dev/null +++ b/component/common/application/google/google_nest.h @@ -0,0 +1,23 @@ +#ifndef GOOGLENEST_H +#define GOOGLENEST_H + +#include + +typedef struct { + int socket; + char *host; + ssl_context ssl; +} googlenest_context; + +int gn_connect(googlenest_context *googlenest, char *host, int port); +void gn_close(googlenest_context *googlenest); +int gn_put(googlenest_context *googlenest, char *uri, char *content); +int gn_patch(googlenest_context *googlenest, char *uri, char *content); +int gn_post(googlenest_context *googlenest, char *uri, char *content, unsigned char *out_buffer, size_t out_len); +int gn_get(googlenest_context *googlenest, char *uri, unsigned char *out_buffer, size_t out_len); +int gn_delete(googlenest_context *googlenest, char *uri); +int gn_stream(googlenest_context *googlenest, char *uri); +void google_retrieve_data_hook_callback(void (*callback)(char *)); + +#endif + diff --git a/component/common/application/jd_joinlink/example_joinlink.c b/component/common/application/jd_joinlink/example_joinlink.c new file mode 100644 index 0000000..3e837b5 --- /dev/null +++ b/component/common/application/jd_joinlink/example_joinlink.c @@ -0,0 +1,675 @@ +/*******************************example_joinlink **************************/ + +#include "autoconf.h" +#include "platform_stdlib.h" +#include "wifi_conf.h" +#include "wifi_structures.h" +#include "osdep_service.h" +#include "lwip_netconf.h" +#include "task.h" +#include "joinlink.h" +#include "cJSON.h" + +#include +#include +#include +#include +#include + +#define MASK_SIZE_JOINLINK 3 +#define SOURCE_PORT 101 + +//gloable +static unsigned char cur_channel = 1; +static unsigned char lock_channel = 1; +static _timer timer_handler_phase2; +static _timer timer_handler_phase1; +static u8 joinlink_finished = 0; +static u8 security_type = 0xff; +static u8 jl_rx_flag = 0; +static rtw_scan_result_t *all_channel_scan_result = NULL; +static rtw_scan_result_t *p_result = NULL; +static int all_channel_ret = 0; +static int phase1_finished = 0; +static int phase2_started = 0; +static u32 start_time = 0; +static u32 current_time = 0; +static int idx = 1; +static int phase1_scanned_channel[14]; +static char ap_bssid[6]; +static char aes_key[] = "123456789"; + +static void* pre_scan_sema; +static int ack_socket; +static struct sockaddr_in to_addr; +static struct sockaddr_in from_addr; +static char header_cmd[] = "cmd"; +static cJSON *ack_content = NULL; +extern struct netif xnetif[]; + +void example_joinlink(void); + +static rtw_result_t joinlink_scan_result_handler(rtw_scan_handler_result_t* malloced_scan_result ) +{ + + static int ApNum = 0; + //TODO: add timer of 2s, wf, 1021 + 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 */ + ++ApNum; + + 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)); + } + // scan finished, wf, 1022 + else + { + rtw_up_sema(&pre_scan_sema); + ApNum = 0; + } + return RTW_SUCCESS; +} + +void* joinlink_all_scan() +{ + int ret = 0; + rtw_scan_result_t *joinlink_scan_buf = NULL; + + if(joinlink_scan_buf != NULL) + free(joinlink_scan_buf); + + joinlink_scan_buf = (rtw_scan_result_t *)malloc(65*sizeof(rtw_scan_result_t)); + if(joinlink_scan_buf == NULL){ + return 0; + } + memset(joinlink_scan_buf, 0, 65*sizeof(rtw_scan_result_t)); + + if((ret = wifi_scan_networks(joinlink_scan_result_handler, joinlink_scan_buf)) != RTW_SUCCESS){ + printf("[ATWS]ERROR: wifi scan failed\n\r"); + free(joinlink_scan_buf); + return 0; + } + return joinlink_scan_buf; +} + +void joinlink_deinit_content() +{ + rtw_del_timer(&timer_handler_phase2); + rtw_del_timer(&timer_handler_phase1); + if(all_channel_scan_result) + { + free(all_channel_scan_result); + all_channel_scan_result = NULL; + } + rtw_free_sema(&pre_scan_sema); + joinlink_deinit(); + + return; +} +static char *jl_itoa(int value) +{ + char *val_str; + int tmp = value, len = 1; + + while((tmp /= 10) > 0) + len ++; + + val_str = (char *) malloc(len + 1); + sprintf(val_str, "%d", value); + + return val_str; +} + +static void get_ip_str(int *ip_int, char *ip_ch) +{ + char *ip_single = NULL; + u8 pos = 0, len = 0; + + for(int i = 0; i < 4; i++) + { + ip_single = jl_itoa(ip_int[i]); + len = strlen(ip_single); + memcpy(ip_ch + pos, ip_single,len); + free(ip_single); + ip_single = NULL; + pos += len; + if(i == 3) + { + *(ip_ch + pos) = 0; + break; + } + *(ip_ch + pos) = '.'; + pos++; + } +} + +static int joinlink_set_ack_content(u8 check_sum) +{ + cJSON_Hooks memoryHook; + memoryHook.malloc_fn = malloc; + memoryHook.free_fn = free; + cJSON_InitHooks(&memoryHook); + + if(ack_content != NULL) + { + cJSON_Delete(ack_content); + ack_content = NULL; + } + if((ack_content = cJSON_CreateObject()) != NULL) + { + char mac_str[18]; + u8 pos = 0; + memset(mac_str, 0, sizeof(mac_str)); + for(int i = 0; i < 6; i++) + { + sprintf(mac_str + pos, "%02x", xnetif[0].hwaddr[i]); + pos += 2; + if(i != 5) + mac_str[pos++] = ':'; + } + + cJSON_AddItemToObject(ack_content, "deviceid", cJSON_CreateString(mac_str)); + cJSON_AddItemToObject(ack_content, "code", cJSON_CreateNumber(check_sum)); + } + else + { + printf("create jSON object failure\n"); + return -1; + } + + return 0; +} + +#if 1 + +static void recv_cmd(void *para) +{ + int rev_len = 0; + char pkt_buf[16]; + while(1) + { + vTaskDelay(500); + if((rev_len = recvfrom(ack_socket, pkt_buf, sizeof(pkt_buf), 0, NULL, NULL)) >= 0) + { + if(memcmp(pkt_buf, header_cmd, sizeof(header_cmd)) == 0) + { + printf("received reboot command, restart join_link process\n"); + // do we need to reboot? + example_joinlink(); + close(ack_socket); + break; + } + } + } + vTaskDelete(NULL); + return; +} + +static int send_ack(int *dest_ip, int dest_port, u8 sum) +{ +#if CONFIG_LWIP_LAYER + int ack_transmit_round; + char ip[16]; + char *jsonString = NULL; + int sended_data = 0; + + if(joinlink_set_ack_content(sum) == -1) + return -1; + + jsonString = cJSON_Print(ack_content); + if(jsonString == NULL) + { + printf("json string convert failure\n"); + cJSON_Delete(ack_content); + return -1; + } + + get_ip_str(dest_ip, ip); + + ack_socket = socket(PF_INET, SOCK_DGRAM, IP_PROTO_UDP); + if (ack_socket == -1) { + printf("create socket failure\n"); + return -1; + } + + FD_ZERO(&to_addr); + to_addr.sin_family = AF_INET; + to_addr.sin_port = htons(dest_port); + to_addr.sin_addr.s_addr = htonl(INADDR_ANY); + + FD_ZERO(&from_addr); + from_addr.sin_family = AF_INET; + from_addr.sin_port = htons(SOURCE_PORT); + to_addr.sin_addr.s_addr = inet_addr(ip); + + if(bind(ack_socket, (struct sockaddr *)&from_addr, sizeof(from_addr)) < 0) + { + printf("bind to source port error\n"); + return -1; + } + + for (ack_transmit_round = 0; ack_transmit_round < 5; ack_transmit_round++) { + sended_data = sendto(ack_socket, (unsigned char *)jsonString, strlen(jsonString), 0, (struct sockaddr *) &to_addr, sizeof(struct sockaddr)); + //printf("\r\nAlready send %d bytes data\n", sended_data); + vTaskDelay(100); /* delay 100 ms */ + } + + if(xTaskCreate(recv_cmd, (char const *)"recv_cmd", 1512, NULL, tskIDLE_PRIORITY + 2, NULL) != pdPASS) + printf("%s xTaskCreate failed\n", __FUNCTION__); + + close(ack_socket); + if(jsonString) + { + free(jsonString); + jsonString = NULL; + } + cJSON_Delete(ack_content); +#endif + + return 0; +} +#endif +static void remove_filter() +{ + wifi_disable_packet_filter(1); + wifi_disable_packet_filter(2); + wifi_remove_packet_filter(1); + wifi_remove_packet_filter(2); +} + +int joinlink_finish(unsigned char security_type) +{ + int ret = 0; + int retry = 3; + unsigned char pscan_config = 1; + joinlink_result_t result; + rtw_security_t security_mode; + + wifi_set_promisc(RTW_PROMISC_DISABLE,NULL,0); + remove_filter(); + + pscan_config = PSCAN_ENABLE | PSCAN_SIMPLE_CONFIG; + ret = joinlink_get_result(&result); + if (ret == 0) { + printf("get result OK\n"); + //printf("\r\n joinlink get result ok,ssid = %s, pwd = %s,ssid length = %d,pwd length = %d", + // result.ssid, result.pwd, result.ssid_length,result.pwd_length); + } + else{ + printf("joinlink result not get!\n"); + joinlink_deinit_content(); + return -1; + } + //ap security type + switch(security_type){ + case RTW_ENCRYPTION_OPEN: + security_mode = RTW_SECURITY_OPEN; + break; + case RTW_ENCRYPTION_WEP40: + case RTW_ENCRYPTION_WEP104: + security_mode = RTW_SECURITY_WEP_PSK; + break; + case RTW_ENCRYPTION_WPA_TKIP: + case RTW_ENCRYPTION_WPA_AES: + case RTW_ENCRYPTION_WPA2_TKIP: + case RTW_ENCRYPTION_WPA2_AES: + case RTW_ENCRYPTION_WPA2_MIXED: + security_mode = RTW_SECURITY_WPA2_AES_PSK; + break; + case RTW_ENCRYPTION_UNKNOWN: + case RTW_ENCRYPTION_UNDEF: + default: + printf("unknow security mode,connect fail!\n"); + } + +#if 1 + while(1){ + if(wifi_set_pscan_chan(&lock_channel, &pscan_config, 1) < 0){ + printf("ERROR: wifi set partial scan channel fail\n"); + break; + } + printf("wifi_connect\n"); + //printf("ap_bssid: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", ap_bssid[0],ap_bssid[1],ap_bssid[2],ap_bssid[3],ap_bssid[4],ap_bssid[5]); + + + ret = wifi_connect((unsigned char *)result.ssid, security_mode, + (unsigned char *)result.pwd, result.ssid_length, + result.pwd_length, + 0,NULL); + + if(ret == RTW_SUCCESS){ + printf("Connect ok!\n"); +#if CONFIG_LWIP_LAYER + /* If not rise priority, LwIP DHCP may timeout */ + vTaskPrioritySet(NULL, tskIDLE_PRIORITY + 3); + /* Start DHCP Client */ + ret = LwIP_DHCP(0, DHCP_START); + vTaskPrioritySet(NULL, tskIDLE_PRIORITY + 1); +#endif + break; + } + if (retry == 0) { + break; + } + + retry--; + } + if(send_ack(result.source_ip, result.source_port, result.sum) != 0) + printf("send ack failure\n"); +#endif + + joinlink_deinit_content(); + return 0; + +} +// handler for phase2 +void timer_handler_phase2_func(void *FunctionContext) +{ + // do not switch channel while handle frames, wf, 1021 + if(jl_rx_flag){ + rtw_set_timer(&timer_handler_phase2, CHANNEL_SWITCH_TIME - 25); + } else { + if(cur_channel >= 13) + {cur_channel = 1;} + else + cur_channel ++; + wifi_set_channel(cur_channel); + rtw_set_timer(&timer_handler_phase2, CHANNEL_SWITCH_TIME); + } + + //printf("phase2:wifi switch channel to %d\n",cur_channel); + return; +} + +// timer handler for the 1st phase, wf, 1022 +void timer_handler_phase1_func(void *FunctionContext) +{ + // do not switch channel while handle frames, wf, 1021 + if(jl_rx_flag){ + rtw_set_timer(&timer_handler_phase1, SSID_SWITCH_TIME - 25); + } + // switch ssid, wf, 1022 + else + { + if(idx >= 14) + { + phase1_finished = 1; + printf("wifi: phase1 scan finished\n"); + printf("wifi: start phase2 scan\n"); +// move from pkt handler to here in case no pkt to trigue phase2 +#if 1 + if(phase1_finished) + { + phase1_finished = 0; + phase2_started = 1; + rtw_cancel_timer(&timer_handler_phase1); + //start phase2 for ch1~ch13 + cur_channel = 1; + wifi_set_channel(cur_channel); + + rtw_init_timer(&timer_handler_phase2, NULL, &timer_handler_phase2_func, NULL, "phase_2"); + rtw_set_timer(&timer_handler_phase2, CHANNEL_SWITCH_TIME); + } +#endif + return; + } + + while(idx < 14) + { + if(phase1_scanned_channel[idx]) + { + wifi_set_channel(idx); + rtw_set_timer(&timer_handler_phase1, SSID_SWITCH_TIME); + //printf("phase1: wifi switch channel to %d\n",idx); + idx++; + break; + } + else + { + if(idx == 13) + rtw_set_timer(&timer_handler_phase1, SSID_SWITCH_TIME); + idx++; + } + + } + + } + return; +} + +static void rtl_frame_recv_handle(unsigned char *buf, int len, unsigned char *da, unsigned char *sa, void *user_data) { + + int ret = 0; + int fixed_channel; + char scanned_ssid[50] = {0}; + unsigned char *current_bssid = NULL; + int scanned_ssid_len = 0; + + //set this flag prevent joinlink_recv interruptted by timer,since timer has higher priority + jl_rx_flag = 1; + if (joinlink_finished) { + jl_rx_flag = 0; + return; + } + + ret = joinlink_recv(da, sa, len, user_data); + if(ret == JOINLINK_STATUS_CHANNEL_LOCKED) + { + if(phase2_started) + { + phase2_started = 0; + rtw_cancel_timer(&timer_handler_phase2); + } + else + rtw_cancel_timer(&timer_handler_phase1); + + lock_channel = cur_channel; + security_type = ((ieee80211_frame_info_t *)user_data)->encrypt; + printf("JoinLink locked to channel[%d]\n",lock_channel); + + current_bssid = buf + 4 + ETH_ALEN; + memcpy(ap_bssid, current_bssid, 6); + + fixed_channel = promisc_get_fixed_channel(current_bssid, scanned_ssid, &scanned_ssid_len); + if (fixed_channel != 0) { + printf("JoinLink force fixed to channel[%d]\r\n",fixed_channel); + printf("JoinLink ssid scanned[%s]\r\n",scanned_ssid); + wifi_set_channel(fixed_channel); + } + + } + else if(ret == JOINLINK_STATUS_COMPLETE){ + //wifi_set_promisc(RTW_PROMISC_DISABLE,NULL,0); + joinlink_finished = 1; + printf("quit promisc mode!\r\n"); + } + //release flag + jl_rx_flag = 0; + + return; +} + + +// callback for promisc packets, like rtk_start_parse_packet in SC, wf, 1021 +void wifi_promisc_rx(unsigned char* buf, unsigned int len, void* user_data) +{ + unsigned char * da = buf; + unsigned char * sa = buf + ETH_ALEN; + + if (joinlink_finished) + return; + + rtl_frame_recv_handle(buf, len, da, sa, user_data); + return; + +} + +// the entry point for joinlink +void joinlink_process(void *param) +{ + + while(1) + { + current_time = xTaskGetTickCount(); + + if(joinlink_finished) + { + printf("joinlink finished\n"); + break; + } + + if((current_time - start_time) > JOINLINK_TIME * configTICK_RATE_HZ) + { + printf("joinlink timeout\n"); + break; + } + + vTaskDelay(500); + } + + joinlink_finish(security_type); + + vTaskDelete(NULL); + return; +} + +int joinlink_init_content() +{ + + int ret = 0; + ret = joinlink_init(); + if(ret < 0){ + printf("JoinLink init failed!\n"); + return ret; + } + memset(phase1_scanned_channel, 0, sizeof(phase1_scanned_channel)); + security_type = 0xff; + cur_channel = 1; + lock_channel = 1; + joinlink_finished = 0; + jl_rx_flag = 0; + p_result = NULL; + all_channel_ret = 0; + phase1_finished = 0; + phase2_started = 0; + idx = 1; + rtw_init_sema(&pre_scan_sema, 0); + memset(ap_bssid, 0, sizeof(ap_bssid)); + set_aes_key(aes_key, sizeof(aes_key) - 1); + + return 0; +} + +// ret:1 indicate suc, else fail +int scan_all_channel() +{ + all_channel_scan_result = (rtw_scan_result_t *)joinlink_all_scan(); + + if(all_channel_scan_result == NULL) + return 0; + else + return 1; + +} + +void get_phase1_channel() +{ + p_result = all_channel_scan_result; + while(p_result->channel) + { + if((p_result->channel >= 1) && (p_result->channel <= 13)) + phase1_scanned_channel[p_result->channel] = 1; + p_result++; + } + return; +} + +// now only accept mcast and bcast pkt +static void filter_add_enable() +{ + u8 mask[MASK_SIZE_JOINLINK]={0xFF,0xFF,0xFF}; + u8 pattern[MASK_SIZE_JOINLINK]={0x01,0x00,0x5e}; + u8 pattern_bcast[MASK_SIZE_JOINLINK]={0xff,0xff,0xff}; + + rtw_packet_filter_pattern_t packet_filter; + rtw_packet_filter_pattern_t packet_filter_bcast; + rtw_packet_filter_rule_e rule; + + packet_filter.offset = 0; + packet_filter.mask_size = 3; + packet_filter.mask = mask; + packet_filter.pattern = pattern; + + packet_filter_bcast.offset = 0; + packet_filter_bcast.mask_size = 3; + packet_filter_bcast.mask = mask; + packet_filter_bcast.pattern = pattern_bcast; + + rule = RTW_POSITIVE_MATCHING; + + wifi_init_packet_filter(); + wifi_add_packet_filter(1, &packet_filter,rule); + wifi_add_packet_filter(2, &packet_filter_bcast,rule); + + wifi_enable_packet_filter(1); + wifi_enable_packet_filter(2); +} + + +void joinlink_start(void *param) +{ + joinlink_finished = 0; + start_time = xTaskGetTickCount(); + + if(xTaskCreate(joinlink_process, (char const *)"JoinLink", 1512, NULL, tskIDLE_PRIORITY + 2, NULL) != pdPASS) + printf("%s xTaskCreate failed\n", __FUNCTION__); + + if (joinlink_init_content() < 0) + printf("joinlink init fail!\n"); + while(1) + { + if(wifi_is_ready_to_transceive(RTW_STA_INTERFACE) == RTW_SUCCESS) + break; + else + vTaskDelay(3000); + } + all_channel_ret = scan_all_channel(); + + if (rtw_down_sema(&pre_scan_sema) == _FAIL) + printf("%s, Take Semaphore Fail\n", __FUNCTION__); + + //printf("\npre scan finished\n"); + + //set wifi to station mode,enable promisc mode and timer to change channel + wifi_enter_promisc_mode(); + filter_add_enable(); + + /* enable all 802.11 packets*/ + wifi_set_promisc(RTW_PROMISC_ENABLE, wifi_promisc_rx, 1); + + //init timer handler,and set timer hanler funcion + if(all_channel_ret) + { + printf("\nstart the phase1 scan\n"); + get_phase1_channel(); + rtw_init_timer(&timer_handler_phase1, NULL, &timer_handler_phase1_func, NULL, "phase1_timer"); + rtw_set_timer(&timer_handler_phase1, SSID_SWITCH_TIME); + } + else + { + printf("phase1 scan fail, start phase2 scan\n"); + rtw_init_timer(&timer_handler_phase2, NULL, &timer_handler_phase2_func, NULL, "phase2_timer"); + wifi_set_channel(cur_channel); + rtw_set_timer(&timer_handler_phase2, CHANNEL_SWITCH_TIME); + } + + vTaskDelete(NULL); + return; +} + +void example_joinlink(void) +{ + if(xTaskCreate(joinlink_start, (char const *)"JoinLink_entry", 1512, NULL, tskIDLE_PRIORITY + 2, NULL) != pdPASS) + printf("%s xTaskCreate failed\n", __FUNCTION__); +} \ No newline at end of file diff --git a/component/common/application/jd_joinlink/joinlink.c b/component/common/application/jd_joinlink/joinlink.c new file mode 100644 index 0000000..73be5ad --- /dev/null +++ b/component/common/application/jd_joinlink/joinlink.c @@ -0,0 +1,1100 @@ +/******************************* joinlink **************************/ +//includes +#include "joinlink.h" + +// macro +#define NUM_MCAST 53 // the max len of pkt in mcast, original: 13 +#define NUM_BCAST 36 // the max number of index of bcast +#define HEAD_LEN 9 // sum(1 byte) + pwd_len(1 byte) + port(2 byte) + ip(4 byte) + ssid_len(1 byte) +#define NUM_IDX 10 // number of index in bcast +#define NUM_PKT 4 // number of packets for every index +#define SEQ_INCREMENT_ONE_BCAST 1 // only the increment of 1 in seq of pkt is accepted + +static char smac[6]; +static u8 decoded_state = 0; +static int joinlink_state_mcast = 0; +static int joinlink_state_bcast = 0; +static u8 sync_label_mcast = 0; +static u8 version_mcast = 0; +// every pkt has two byte +static u8 *raw_data_mcast = NULL; +static u8 *decrypted_data_mcast = NULL; +static u8 count_mcast = 0; +static u8 sum_mcast = 0; // the total len of ssid and pwd +static char pass_len = -1; +static u8 ssid_len = 0; +static u8 ssid_offset = 0; +static u8 odd_check = 0; +static u8 total_len_mcast = 0; +static u8 *recved_flag_mcast = NULL; +static u8 range_mcast[NUM_MCAST >> 3]; // the range for aes decryption +static u8 decryp_flag_mcast[NUM_MCAST >> 3]; + +static u8 sync_label_bcast = 0; +static u8 version_bcast_ready = 0; +static u8 version_bcast = 0; +static u8 count_in_idx_bcast = 0; +static u8 count_decoded_bcast = 0; +static unsigned short seq_now_bcast = 0; +static u8 locked_bssid_bcast[6]; +static u8 ssid_offset_bcast = 0; + +// for data phase in bcast +// 0: wating index pkt, 1: waiting info pkt +// TODO: need to fix bssid/ssid for bcast to filter unnecessary pkt +static u8 data_phase_state_bcast = 0; +static u8 *raw_data_bcast = NULL; +static u8 *decrypted_data_bcast = NULL; + +static u8 version_CRC = 0; +static u8 *decoded_flag_bcast = NULL; +static u8 current_idx_bcast = 0; + +static u8 sum_bcast = 0; +static char pass_len_bcast = -1; +static u8 ssid_len_bcast = 0; +static u8 fc_version_bcast = 0; +static u8 fc_data_bcast = 0; +static u8 idx_CRC = 0; +static u8 idx_data = 0; + +//store decode result of AP profile +joinlink_result_t *AP_profile = NULL; + +// AES decryption related +static u8 aes_iv[16]; +static u8 aes_key[16]; +static u8 ssid_range_mcast = 255; +static u8 decryp_data_buf[16]; +/* +ret: 0, success, -1, failure +*/ +int joinlink_init() +{ + decoded_state = 0; + joinlink_state_mcast = 0; + joinlink_state_bcast = 0; + sync_label_mcast = 0; + version_mcast = 0; + + raw_data_mcast = (u8 *)malloc(NUM_MCAST*2); + decrypted_data_mcast = (u8 *)malloc(NUM_MCAST*2); + recved_flag_mcast = (u8 *)malloc(NUM_MCAST); + raw_data_bcast = (u8 *)malloc(NUM_BCAST*NUM_PKT); + decrypted_data_bcast = (u8 *)malloc(NUM_BCAST*NUM_PKT); + decoded_flag_bcast = (u8 *)malloc(NUM_BCAST); + AP_profile = (joinlink_result_t *)malloc(sizeof(joinlink_result_t)); + + if(!raw_data_mcast || !decrypted_data_mcast || !recved_flag_mcast|| + !raw_data_bcast || !decrypted_data_bcast || !decoded_flag_bcast|| + !AP_profile) + { + printf("join_link: malloc memory fail\n"); + return -1; + } + + memset(raw_data_mcast, 0, NUM_MCAST*2); + count_mcast = 0; + sum_mcast = 0; + pass_len = -1; + ssid_len = 0; + ssid_offset = 0; + odd_check = 0; + total_len_mcast = 0; + memset(recved_flag_mcast, 0, NUM_MCAST); + + sync_label_bcast = 0; + version_bcast_ready = 0; + version_bcast = 0; + seq_now_bcast = 0; + memset(locked_bssid_bcast, 0, sizeof(locked_bssid_bcast)); + + data_phase_state_bcast = 0; + memset(raw_data_bcast, 0, NUM_BCAST*NUM_PKT); + version_CRC = 0; + count_in_idx_bcast = 0; + count_decoded_bcast = 0; + memset(decoded_flag_bcast, 0, NUM_BCAST); + current_idx_bcast = 0; + sum_bcast = 0; + pass_len_bcast = -1; + ssid_len_bcast = 0; + fc_version_bcast = 0; + fc_data_bcast = 0; + idx_CRC = 0; + idx_data = 0; + + memset(AP_profile, 0, sizeof(joinlink_result_t)); + memset(smac, 0, sizeof(smac)); + + memset(aes_iv, 0, sizeof(aes_iv)); + memset(aes_key, 0, sizeof(aes_key)); + memset(range_mcast, 0, sizeof(range_mcast)); + memset(decryp_flag_mcast, 0, sizeof(decryp_flag_mcast)); + ssid_range_mcast = 255; + memset(decrypted_data_mcast, 0, NUM_MCAST*2); + memset(decryp_data_buf, 0, sizeof(decryp_data_buf)); + memset(decrypted_data_bcast, 0, NUM_BCAST*NUM_PKT); + ssid_offset_bcast = 0; + + return 0; +} + +// set the aes_key, the max len should be 16 +int set_aes_key(char *key, int len) +{ + if (len <= 0 || len > 16) + return 0; + + memcpy(aes_key, key, len); + if (rtl_crypto_aes_cbc_init(aes_key, sizeof(aes_key)) != 0) + { + printf("AES CBC init failed\n"); + return 0; + } + printf("the AES key is set to %s\n", aes_key); + return 1; +} +// free memory +void joinlink_deinit() +{ + free(raw_data_mcast); + free(decrypted_data_mcast); + free(recved_flag_mcast); + free(raw_data_bcast); + free(decrypted_data_bcast); + free(decoded_flag_bcast); + free(AP_profile); + + raw_data_mcast = NULL; + decrypted_data_mcast = NULL; + recved_flag_mcast = NULL; + raw_data_bcast = NULL; + decrypted_data_bcast = NULL; + decoded_flag_bcast = NULL; + AP_profile = NULL; + + return; +} +// restart joinlink when error +static void joinlink_restart() +{ + joinlink_deinit(); + joinlink_init(); + return; +} +/* +ret: 0, failure; 1 true. +*/ +static int check_sync_mcast(u8 *da) +{ + if((da[3] == 0) && (da[4] == 1) && (da[5] >= 1) && (da[5] <= 3)) + { + sync_label_mcast |= 0x01 << (da[5] - 1); + if(sync_label_mcast == 0x07) + return 1; + else + return 0; + } + else + return 0; +} +// ret: 0, failure; 1 true +static int check_version_mcast(u8 *da) +{ + // 239.0.{Version}.4 + if((da[3] == 0) && (da[5] == 4)) + { + version_mcast = da[4]; + return 1; + } + else + return 0; +} + +static u8 getCrc(u8 *ptr, u8 len) +{ + u8 crc; + u8 i; + crc = 0; + while (len--) + { + crc ^= *ptr++; + for (i = 0; i < 8; i++) + { + if (crc & 0x01) + { + crc = (crc >> 1) ^ 0x8C; + } + else + crc >>= 1; + } + } + return crc; +} +// check whether received enough pkt to decrypt +static u8 decryp_ready(u8 range) +{ + int first = (range << 3) + 1; + u8 count = 0; + while(count < 8) + { + if(!recved_flag_mcast[first + count]) + return 0; + ++count; + } + return 1; +} +// ret: 0 suc, ret: -1 failure +static int decryp_data(u8 decryp_range) +{ + // before decryption dump + memset(decryp_data_buf, 0, sizeof(decryp_data_buf)); + + // this decrpytion API only accept 16 byte size + if (rtl_crypto_aes_cbc_decrypt(raw_data_mcast + (decryp_range << 4), 16, aes_iv, sizeof(aes_iv), decryp_data_buf) != 0 ) + { + printf("AES CBC decrypt failed\n"); + return -1; + } + memcpy(decrypted_data_mcast + (decryp_range << 4), decryp_data_buf, 16); + // dump encrypted and decrypted data +#if 0 + printf("range %d encryp data:", decryp_range); + for(int i = 0; i < 16; i++) + printf("0x%02x ", raw_data_mcast[(decryp_range << 4) + i]); + printf("\n"); + + printf("range %d decrypted to:", decryp_range); + for(int i = 0; i < 16; i++) + printf("0x%02x ", decrypted_data_mcast[(decryp_range << 4) + i]); + printf("\n"); +#endif + return 0; +} + +// for aes_cbc, need to remove the chain using xor +static void dechain_aes_mcast(u8 range) +{ + if(range != 0) + { + for(int i = 0; i < 16; i++) + decrypted_data_mcast[(range << 4) + i] ^= raw_data_mcast[(range - 1 << 4) + i]; + } + // dump data +#if 0 + printf("range %d dechained to: ", range); + for(int i = 0; i < 16; i++) + printf("0x%02x ", decrypted_data_mcast[(range << 4) + i]); + printf("\n"); +#endif + printf("mcast: block %d is dechained\n", range); + decryp_flag_mcast[range] = 2; + count_mcast += 8; + return; +} +/* +ret: 1, enough data; 0 error or not enough +239.{index}.{byte[i]}{byte[i+1]} +{index} = (CRCLSB*3bit) + (Index*5bit) +*/ +static int check_data_mcast(u8 *da) +{ + u8 raw_index = da[3]; + u8 CRC_index = (raw_index & 0x40) >> 6; + u8 idx = raw_index & 0x3f; + u8 first, second; + u8 range = 0; + int first_in_range = 0; + // check CRC + + // idx is invalid, start with 1 + if((idx > NUM_MCAST) || (idx < 1)) + return 0; + + // CRC check pass + if(((da[4] ^ da[5]) & 0x01) == CRC_index) + { + // already received + if(recved_flag_mcast[idx] == 1) + return 0; + + // new pkt + recved_flag_mcast[idx] = 1; + first = (idx -1) * 2; + second = first + 1; + + raw_data_mcast[first] = da[4]; + raw_data_mcast[second] = da[5]; + printf("mcast: new pkt, idx is %d\n", idx); + // range begins with 0, every 8 pkts belongs to 1 range,e.g idx: {1~8} -> range:0 + range = (idx - 1) >> 3; + // not enough pkt for decryption + if(!decryp_ready(range)) + return 0; + // start to decrypt + first_in_range = range << 4; + if(decryp_data(range) == -1) + { + // clear the received flag for this range + for (int i = 1; i < 9; i++) + recved_flag_mcast[first_in_range + i] = 0; + printf("decryped error in range %d\n",range); + return 0; + } + // decryption success here; + decryp_flag_mcast[range] = 1; + printf("mcast: block %d is decrypted\n", range); + + // this is the sum and pass_len + //if((idx == 1) && (!sum_mcast)) + if(range == 0) + { + dechain_aes_mcast(range); + + sum_mcast = decrypted_data_mcast[0]; + pass_len = decrypted_data_mcast[1]; + printf("mcast: sum_mcast 0x%02x pass_len %d \n",sum_mcast, pass_len); + + // check whether the pass_len is valid + if(pass_len < 0 || pass_len > 64) + { + printf("mcast: pass_len is wrong, clear\n"); + decryp_flag_mcast[range] = 0; + count_mcast -= 8; + for (int i = 1; i < 9; i++) + recved_flag_mcast[first_in_range + i] = 0; + return 0; + } + + // printf("[DEBUG]_mcast: the 2nd flag is %d\n", decryp_flag_mcast[range + 1]); + // check whether 2nd block is ready + if(decryp_flag_mcast[range + 1] == 1) + { + printf("here\n"); + dechain_aes_mcast(range + 1); + } + + if((pass_len & 0x01) == 0) + odd_check = 2; // even + else + odd_check = 1; // odd + // get the idx of pkt which contains the ssid_len info + ssid_offset = 1 + (u8)((8 + pass_len)/2); + ssid_range_mcast = (ssid_offset - 1) >> 3; + printf("ssid_offset %d ssid_range_mcast %d\n",ssid_offset, ssid_range_mcast); +#if 1 + // already dechained + if(decryp_flag_mcast[ssid_range_mcast] == 2) + { + if(total_len_mcast == 0) + { + if(ssid_len == 0) + { + if(odd_check == 2) + ssid_len = decrypted_data_mcast[2 * (ssid_offset - 1)]; + if(odd_check == 1) + ssid_len = decrypted_data_mcast[2 * (ssid_offset - 1) + 1]; + printf("ssid_len is %d\n",ssid_len); + } + total_len_mcast = (u8)((pass_len + ssid_len + HEAD_LEN + 1)/2); + printf("total_len_mcast is recalculated as %d\n",total_len_mcast); + } + } +#endif + } + // need to dechain for the 2nd and following block + else + { + if(decryp_flag_mcast[range - 1] > 0) + dechain_aes_mcast(range); + + if(decryp_flag_mcast[range + 1] == 1) + dechain_aes_mcast(range + 1); + + if(!decryp_flag_mcast[range - 1] && !decryp_flag_mcast[range + 1]) + return 0; + } + // 8 new pkts has been de chained for AES + + // set the ssid_len + if(ssid_range_mcast != 255 && decryp_flag_mcast[ssid_range_mcast] == 2) + { + if(ssid_len == 0) + { + if(odd_check == 2) + ssid_len = decrypted_data_mcast[2 * (ssid_offset - 1)]; + if(odd_check == 1) + ssid_len = decrypted_data_mcast[2 * (ssid_offset - 1) + 1]; + printf("ssid_len is %d\n",ssid_len); + } + } + + // set the total_len + if((pass_len != -1) && (ssid_len != 0)) + { + if(total_len_mcast == 0) + { + total_len_mcast = (u8)((pass_len + ssid_len + HEAD_LEN + 1)/2); + printf("total_len_mcast is calculated as %d\n",total_len_mcast); + } + } + + printf("total_len needed is %d already decrypted %d\n", total_len_mcast, count_mcast); + + if(!total_len_mcast) + { + if(count_mcast >= NUM_MCAST) + return 1; + else + return 0; + } + else + { + //printf("count_mcast is %d total_len_mcast is %d\n"); + if(count_mcast >= total_len_mcast) + { + // check CRC + u8 crc_ret = 0; + printf("enough decrypted pkt, start to check sum\n"); + if((pass_len + ssid_len) & 0x01) + crc_ret = getCrc(decrypted_data_mcast + 1, total_len_mcast * 2 - 1); + else + crc_ret = getCrc(decrypted_data_mcast + 1, total_len_mcast * 2 - 2); + + if(crc_ret == sum_mcast) + {printf("sum check pass\n"); return 1;} + else + { + printf("sum crc check failure, restart\n"); + joinlink_restart(); // fine tune: only restart the mcast part + return 0; + } + } + else + return 0; + } + } + // check CRC failure + else + { + //printf("CRC failure in mcast, getCrc is 0x%02x, CRC is 0x%02x\n",(da[4] ^ da[5]), CRC_index); + return 0; + } + +} +/* +ret: 0, failure; 1 true. +*/ +static int check_sync_bcast(int len) +{ + // make sure the bits larger than 9 is 0 + if(len >= 256) + return 0; + // only the least 9 bits are useful + len &= 0x01ff; + if((len >=1) && (len <=4)) + { + sync_label_bcast |= 0x01 << (len - 1); + if(sync_label_bcast == 0x0f) + return 1; + else + return 0; + } + else + return 0; +} + +/* +{0b10000*5bit}+{CRCLSB*4bit} +{0*1bit}{Version} + ret: 0, failure; 1 true + */ +static int check_version_bcast(int len, u8 i_fc) +{ + version_bcast = 0; + + if(!version_bcast_ready) + { + u8 version_pre_CRC = len & 0x0007; + u8 version_pre_data = (len & 0x01f8) >> 3; + + if(len >= 512) + return 0; + + if(version_pre_data == 0x20) + { + version_bcast_ready = 1; + version_CRC = version_pre_CRC; + // fix the direction(fromDS/toDS) to receive version info + fc_version_bcast = i_fc; + +// printf("get the CRC of version, change to wait version state\n"); + } + + return 0; + } + else + { + if(i_fc != fc_version_bcast) + return 0; + + if((len & 0xff00) != 0) + return 0; + + version_bcast = len & 0x00ff; + if((getCrc(&version_bcast,1) & 0x07) == version_CRC) + { + printf("version CRC pass\n"); + return 1; + } + else + { + //printf("version CRC failure,reset this state, version is 0x%02x calculated CRC is 0x%02x, CRC is 0x%02x\n", + // version_bcast, getCrc(&version_bcast,1), version_CRC); + version_bcast_ready = 0; + } + + } + return 0; +} + +/*ret 1: valid seq, ret 0: invalid seq*/ +static u8 check_and_update_seq(unsigned short frame_seq) +{ + int seq_delta = frame_seq - seq_now_bcast; + +#if SEQ_INCREMENT_ONE_BCAST + if((seq_delta == 1) || (seq_now_bcast == 4095) && (frame_seq == 0)) + { + seq_now_bcast = frame_seq; + return 1; + } + else + { + seq_now_bcast = frame_seq; + return 0; + } +#else + if(((seq_delta <= 10) && (seq_delta >= 0)) || + ((seq_now_bcast > 4085) && (seq_delta + 4096 <= 10) && (seq_delta + 4096 >= 0))) + { + seq_now_bcast = frame_seq; + //printf("valid seq, seq_delta %d seq_now is updated to %d\n", seq_delta, seq_now_bcast); + return 1; + } + else + { + seq_now_bcast = frame_seq; + //printf("invalid seq, seq_delta %d seq_now is updated to %d\n", seq_delta, seq_now_bcast); + return 0; + } +#endif +} +// idx starts with 1, every 4 is one decryption block +static int decryp_ready_bcast(u8 first_idx) +{ + for(int i = 0; i < 4; i++) + { + if(decoded_flag_bcast[first_idx + i] == 0) + return 0; + } + return 1; +} +// decryption for bcast +static int decryp_data_bcast(u8 idx) +{ + memset(decryp_data_buf, 0, sizeof(decryp_data_buf)); +// dump the encryption info +#if 0 + printf("before decryption of idx %d:", idx); + for(int i = 0; i < 16; i++) + printf("0x%02x ", raw_data_bcast[((idx >> 2) << 4) + i]); + printf("\n"); +#endif + + // this decrpytion API only accept 16 byte size + if (rtl_crypto_aes_cbc_decrypt(raw_data_bcast + ((idx >> 2) << 4), 16, aes_iv, sizeof(aes_iv), decryp_data_buf) != 0 ) + { + printf("AES CBC decrypt failed\n"); + return -1; + } + memcpy(decrypted_data_bcast + ((idx >> 2) << 4), decryp_data_buf, 16); + printf("bcast: blcok %d is decrypted\n", idx >> 2); +// dump the info after decryption +#if 0 + printf("after decryption of idx %d:", idx); + for(int i = 0; i < 16; i++) + printf("0x%02x ", decrypted_data_bcast[((idx >> 2) << 4) + i]); + printf("\n"); +#endif + + return 0; +} +// remove chain for aes cbc for bcast mode +static void dechain_aes_bcast(u8 idx) +{ + u8 first_idx = (idx >> 2) << 4; + if(idx != 1) + { + for(int i = 0; i < 16; i++) + decrypted_data_bcast[first_idx + i] ^= raw_data_bcast[first_idx - 16 + i]; + } + count_decoded_bcast += 4; + // set the dechained flag + for(int i = 0; i < 4; i++) + decoded_flag_bcast[idx + i] = 3; + // dump the info after dechain +#if 0 + printf("idx %d is de chained to: ", idx); + for(int i = 0; i < 16; i++) + printf("0x%02x ", decrypted_data_bcast[first_idx + i]); + printf("\n"); +#endif + printf("bcast: block %d is dechained\n", idx >> 2); + return; +} + +/* +{EncodeIndex*5bit}+{CRCLSB*4bit} +{0*1bit}{Byte(i+0) *8bit} +{0*1bit}{Byte(i+1) *8bit} +{0*1bit}{Byte(i+2) *8bit} +{0*1bit}{Byte(i+3) *8bit} +*/ +static int check_data_bcast(int len, u8 i_fc, unsigned short frame_seq, unsigned const char *temp_bssid) +{ + // waiting index pkt + if(!data_phase_state_bcast) + { + + // make sure the 9th bit is 1 and bit larger than 9 is 0 + if(((len & 0x0fff) >= 512) || ((len & 0x0fff) <= 256)) + return 0; + // idx_data is increase from 1, not 0 + idx_data = (len & 0x00f8) >> 3; + if(idx_data == 0) + return 0; + + if(idx_data > NUM_BCAST) + { + printf("index is too large\n"); + return 0; + } + + // already decoded this idx + if(decoded_flag_bcast[idx_data] >= 1) + return 0; + else + { + current_idx_bcast = idx_data; + count_in_idx_bcast = 0; + data_phase_state_bcast = 1; + idx_CRC = len & 0x0007; + seq_now_bcast = frame_seq; + //printf("idx_CRC is 0x%02x len is 0x%02x\n",idx_CRC, len); + fc_data_bcast = i_fc; + //printf("waiting data pkt of idx %d, locked in i_fc %d, seq_now %d\n", + // current_idx_bcast,fc_data_bcast,seq_now_bcast); + return 0; + } + + } + // waiting info pkt + else + { + u8 array_idx = 0; + // check whether the data is valid, the 9th bit should be 0 + if(len >= 256) + { + //printf("not info pkt\n"); + return 0; + } + + // only receive the data from the previous idx direction + if(i_fc != fc_data_bcast) + return 0; + + array_idx = 4 * (current_idx_bcast - 1); + + //printf("from bssid 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", + // temp_bssid[0],temp_bssid[1],temp_bssid[2],temp_bssid[3],temp_bssid[4],temp_bssid[5]); + // check whether seq is valid + if(check_and_update_seq(frame_seq) == 0) + { + //memset(raw_data_bcast + array_idx, 0, 4); + data_phase_state_bcast = 0; + return 0; + } + + raw_data_bcast[array_idx + count_in_idx_bcast] = len & 0x00ff; + count_in_idx_bcast++; + + //printf("len 0x%02x, info 0x%02x, i_fc %d i_seq %d\n",len, len & 0x00ff, i_fc, frame_seq); + if(count_in_idx_bcast != NUM_PKT) + return 0; + else + { + u8 temp_ret = 0; + u8 first_idx = 0; + +#if 0 + printf("enough data pkt for idx, check CRC\n",current_idx_bcast); + printf("data to be decoded in idx %d: 0x%02x 0x%02x 0x%02x 0x%02x\n",current_idx_bcast, + *(raw_data_bcast + array_idx),*(raw_data_bcast + array_idx + 1), + *(raw_data_bcast + array_idx + 2),*(raw_data_bcast + array_idx + 3)); +#endif + + // assume first encryption and then CRC, so CRC check first and then decryption for receiver. + temp_ret = getCrc(raw_data_bcast + array_idx, 4) & 0x07; + //printf("calculated CRC is 0x%02x true CRC is 0x%02x\n",temp_ret, idx_CRC); + // CRC pass + if(temp_ret == idx_CRC) + { + printf("bcast: idx %d is decoded\n",current_idx_bcast); + // the first idx in every decryption block + first_idx = 1 + ((current_idx_bcast - 1 >> 2) << 2); + // set the flag of this idx to 1, indicate pass CRC but not yet to decrypt + decoded_flag_bcast[current_idx_bcast] = 1; + // not enough neighbor idx for decryption + if(decryp_ready_bcast(first_idx) == 0) + return 0; + + if(decryp_data_bcast(first_idx) == -1) + { + for(int i = 0; i < 4; i++) + decoded_flag_bcast[first_idx + i] = 0; + // clear the 4 idx data in this block; + memset(raw_data_bcast + ((current_idx_bcast - 1 >> 2) << 4), 0, 16); + data_phase_state_bcast = 0; + return 0; + } + // decryption PASS + // set the decryption flag + for(int i = 0; i < 4; i++) + decoded_flag_bcast[first_idx + i] = 2; + + // if 1st block, get the pass_len + if(current_idx_bcast <= 4) + { + dechain_aes_bcast(first_idx); + sum_bcast = *decrypted_data_bcast; + pass_len_bcast = *(decrypted_data_bcast + 1); + // make sure the pass len is in the right range {0,63} + if((pass_len_bcast > 63) || (pass_len_bcast < 0)) + { + printf("pass_len is wrong, clear\n"); + for(int i = 0; i < 4; i++) + decoded_flag_bcast[first_idx + i] = 0; + count_decoded_bcast -= 4; + // clear the 4 idx data in this block; + memset(raw_data_bcast + ((current_idx_bcast - 1 >> 2) << 4), 0, 16); + data_phase_state_bcast = 0; + return 0; + } + printf("sum_bcast is %d pass_len_bcast is %d\n",sum_bcast, pass_len_bcast); + // recalculate ssid_len if the idx containning ssid_len is already decoded + + // to de chain the neighbor block + if(decryp_ready_bcast(first_idx + 4)) + dechain_aes_bcast(first_idx + 4); + + ssid_offset_bcast = (8 + pass_len_bcast)/4 + 1; + if(decoded_flag_bcast[ssid_offset_bcast] == 3) + { + ssid_len_bcast = *(decrypted_data_bcast + 8 + pass_len_bcast); + // check whether ssid len is in the right range {0,32} + if(ssid_len_bcast > 32) + { + //memset(raw_data_bcast + 4 * (2 + pass_len_bcast/4), 0, 4); + data_phase_state_bcast = 0; + for(int i = 0; i < 4; i++) + decoded_flag_bcast[(ssid_len_bcast - 1 >> 2) + i] = 0; + count_decoded_bcast -= 4; + printf("ssid_len_bcast is wrong, clear idx %d\n", ((8 + pass_len_bcast)/4 + 1)); + return 0; + } + printf("recalculated ssid_len_bcast is %d\n",ssid_len_bcast); + } + } + // for the 2nd and following block, need the preceeding block to de chain + else + { + if(decryp_ready_bcast(first_idx - 4)) + dechain_aes_bcast(first_idx); + + if(decryp_ready_bcast(first_idx + 4)) + dechain_aes_bcast(first_idx + 4); + + if(!decryp_ready_bcast(first_idx - 4) && !decryp_ready_bcast(first_idx + 4)) + return 0; + } + // check whether ssid_len idx has been dechained + for(int i = 0; i < 4; i++) + { + if((pass_len_bcast != -1) && (decoded_flag_bcast[ssid_offset_bcast] == 3)) + { + ssid_len_bcast = *(decrypted_data_bcast + 8 + pass_len_bcast); + // make sure ssid_len is valid in the range {0, 32} + if(ssid_len_bcast > 32) + { + //memset(raw_data_bcast + 4 * (2 + pass_len_bcast/4), 0, 4); + data_phase_state_bcast = 0; + for(int i = 0; i < 4; i++) + decoded_flag_bcast[(ssid_offset_bcast >> 2) << 2 + i + 1] = 0; + count_decoded_bcast -= 4; + printf("ssid_len_bcast is wrong\n"); + return 0; + } + printf("ssid_len_bcast is %d\n",ssid_len_bcast); + break; + } + } + // check whether enough + if((ssid_len_bcast != 0) && (pass_len_bcast != -1)) + { + u8 total_len_bcast = HEAD_LEN + ssid_len_bcast + pass_len_bcast; + printf("needed %d pkt, decoded %d\n",(u8)((total_len_bcast + 3)/4),count_decoded_bcast); + if(count_decoded_bcast >= (u8)((total_len_bcast + 3)/4)) + { + printf("enough decoded packets, start to check sum\n"); + if(getCrc(decrypted_data_bcast + 1,total_len_bcast - 1) == sum_bcast) + { + printf("sum check pass in bcast\n"); + return 1; + } + else + { + //printf("bcast sum check failure, restart\n"); + joinlink_restart(); // fine tune: only restart the bcast part + return 0; + } + } + } + + data_phase_state_bcast = 0; + } + else + { + memset(raw_data_bcast + 4 * (current_idx_bcast - 1), 0, 4); + data_phase_state_bcast = 0; + printf("CRC failure of idx %d\n",current_idx_bcast); + return 0; + } + } + + } + + return 0; +} +/* +ret: 0, failure, 1 true +if success, assign the AP profile to a structure. +*/ +static int decode_AP_profile(u8 *raw_data) +{ + int pos = 0; + + AP_profile->sum = raw_data[pos]; + pos++; + printf("AP_profile: sum %d\n",AP_profile->sum); + + AP_profile->pwd_length = raw_data[pos]; + pos++; + printf("AP_profile: pwd_len %d\n",AP_profile->pwd_length); + + if(AP_profile->pwd_length > 64) + { + printf("the pwd len: %d, larger than 64\n",AP_profile->pwd_length); + return 0; + } + + memcpy(AP_profile->pwd, (raw_data + pos), AP_profile->pwd_length); + pos += AP_profile->pwd_length; + printf("AP_profile: pwd %s\n",AP_profile->pwd); + + AP_profile->source_ip[0] = *(raw_data + pos); + AP_profile->source_ip[1] = *(raw_data + pos + 1); + AP_profile->source_ip[2] = *(raw_data + pos + 2); + AP_profile->source_ip[3] = *(raw_data + pos + 3); + + pos += 4; + printf("AP_profile: sip %d %d %d %d\n",AP_profile->source_ip[0], + AP_profile->source_ip[1], + AP_profile->source_ip[2], + AP_profile->source_ip[3]); + // assume the high byte is the most significant + #if 1 + AP_profile->source_port = ((unsigned int)(*(raw_data + pos + 1)) << 8) | (*(raw_data + pos)); + //printf("port high_part, low_part: %d %d\n", *(raw_data + pos + 1), *(raw_data + pos)); + #endif + + pos += 2; + printf("AP_profile: port %d\n",AP_profile->source_port); + + AP_profile->ssid_length = *(raw_data + pos); + pos++; + printf("AP_profile: ssid_len %d\n",AP_profile->ssid_length); + + if(AP_profile->ssid_length > 64) + { + printf("the ssid len: %d, larger than 64\n",AP_profile->ssid_length); + return 0; + } + memcpy(AP_profile->ssid, (raw_data + pos), AP_profile->ssid_length); + printf("AP_profile: ssid %s\n",AP_profile->ssid); + + return 1; +} + +joinlink_status_t joinlink_recv(u8 *da, u8 *sa, int len, void *user_data) +{ + joinlink_status_t ret; + const ieee80211_frame_info_t *promisc_info = user_data; + // 1 from ds, 2 to ds + u8 i_fc = ((promisc_info->i_fc & 0x0100) == 0x0100)? 2: 1; + unsigned short frame_seq = promisc_info->i_seq; + unsigned const char *temp_bssid = promisc_info->bssid; + + // for mcast + if(!((da[0] == 0xff) && (da[1] == 0xff) && (da[2] == 0xff) && + (da[3] == 0xff) && (da[4] == 0xff) && (da[5] == 0xff))) + { + if(joinlink_state_mcast == 0) + { + if(!check_sync_mcast(da)) + return JOINLINK_STATUS_CONTINUE; + else + { + // TODO: consider to fix source mac here + joinlink_state_mcast = 1; + memcpy(smac, sa, 6); + printf("turn to wait version state\n"); + return JOINLINK_STATUS_CONTINUE; + } + + } + else if(joinlink_state_mcast == 1) + { + // only accept the pkt from fixed source mac + if(memcmp(smac, sa, 6)) + return JOINLINK_STATUS_CONTINUE; + + if(!check_version_mcast(da)) + return JOINLINK_STATUS_CONTINUE; + else + { + joinlink_state_mcast = 2; + printf("mcast version is %d\n",version_mcast); + printf("turn to wait data state\n"); + return JOINLINK_STATUS_CHANNEL_LOCKED; + } + } + else if(joinlink_state_mcast == 2) + { + if(memcmp(smac, sa, 6)) + return JOINLINK_STATUS_CONTINUE; + + if(!check_data_mcast(da)) + return JOINLINK_STATUS_CONTINUE; + else + { + printf("enough packets, start to decode AP profile\n"); + // AP profile has been gotten + if(!decode_AP_profile(decrypted_data_mcast)) + { + printf("decode failure, restart joinlink\n"); + joinlink_restart(); + //TODO: intialize the data structure to restart receive data + return JOINLINK_STATUS_CONTINUE; + } + else + { + decoded_state = 1; + return JOINLINK_STATUS_COMPLETE; + } + } + } + } + // for bcast + else + { + len -= 42; // remove the unnecessary part + + if(joinlink_state_bcast == 0) + { + if(!check_sync_bcast(len)) + return JOINLINK_STATUS_CONTINUE; + else + { + // fix the smac and bssid + memcpy(smac, sa, 6); + memcpy(locked_bssid_bcast, temp_bssid, 6); + joinlink_state_bcast = 1; + printf("change to bcast_state_1, lock channel\n"); + return /*JOINLINK_STATUS_CONTINUE*/JOINLINK_STATUS_CHANNEL_LOCKED; + } + + } + else if(joinlink_state_bcast == 1) + { + if(memcmp(smac, sa, 6) || memcmp(temp_bssid, locked_bssid_bcast, 6)) + return JOINLINK_STATUS_CONTINUE; + + if(!check_version_bcast(len, i_fc)) + return JOINLINK_STATUS_CONTINUE; + else + { + joinlink_state_bcast = 2; + printf("change to bcast_state_2\n"); + return /*JOINLINK_STATUS_CHANNEL_LOCKED*/JOINLINK_STATUS_CONTINUE; + } + } + else if(joinlink_state_bcast == 2) + { + if(memcmp(smac, sa, 6) || memcmp(temp_bssid, locked_bssid_bcast, 6)) + return JOINLINK_STATUS_CONTINUE; + + if(!check_data_bcast(len, i_fc, frame_seq, temp_bssid)) + return JOINLINK_STATUS_CONTINUE; + else + { + // AP profile has been gotten + if(!decode_AP_profile(decrypted_data_bcast)) + { + printf("decode failure, restart joinlink\n"); + //TODO: intialize the data structure to restart receive data + return JOINLINK_STATUS_CONTINUE; + } + else + { + decoded_state = 1; + return JOINLINK_STATUS_COMPLETE; + } + } + } + } + ret = JOINLINK_STATUS_CONTINUE; + return ret; +} + +/* + * copy the decode AP info to user space +* store the AP profile to result; +* ret: 0, success +* ret: -1, failure + */ +int joinlink_get_result(joinlink_result_t *result) +{ + if(decoded_state == 0) + return -1; + else + { + memcpy(result, AP_profile, sizeof(joinlink_result_t)); + return 0; + } +} + + + +/*********************************************************/ diff --git a/component/common/application/jd_joinlink/joinlink.h b/component/common/application/jd_joinlink/joinlink.h new file mode 100644 index 0000000..5c3b151 --- /dev/null +++ b/component/common/application/jd_joinlink/joinlink.h @@ -0,0 +1,64 @@ +/******************************* joinlink **************************/ +#ifndef __JOINLINK_H +#define __JOINLINK_H + +#include "autoconf.h" +#include "platform_stdlib.h" +#include "wifi_conf.h" +#include "wifi_structures.h" +#include "osdep_service.h" +#include "lwip_netconf.h" +#include "task.h" +#include "hal_crypto.h" + +#define SSID_SWITCH_TIME 500 //ssid switch time in phase1,units:ms, 50 +#define CHANNEL_SWITCH_TIME 500 //channel switch time in phase2,units:ms, 50 +#define JOINLINK_TIME 120 //timeout for joinlink process, units: s + +/* + * store AP profile after successfully decode + * SUM +lengthpass+IP+Port+lengthSSID) + */ +typedef struct +{ + unsigned char sum; + unsigned char pwd_length; + char pwd[65]; + int source_ip[4]; + unsigned int source_port; + unsigned char ssid_length; + char ssid[65]; +} joinlink_result_t; + +/* + * return value of joinlink_recv() + */ +typedef enum +{ + JOINLINK_STATUS_CONTINUE = 0, + JOINLINK_STATUS_CHANNEL_LOCKED = 1, + JOINLINK_STATUS_COMPLETE = 2 +} joinlink_status_t; + +//initialize the related data structure +int joinlink_init(); +/* + handler to decode pkt + */ +joinlink_status_t joinlink_recv(unsigned char *da, unsigned char *sa, int len, void *user_data); + +/* + * get the AP profile after decode + */ +int joinlink_get_result(joinlink_result_t *result); + +/* + * set the aes_key, the max len should be 16 + * ret 1: success; ret 0: the len is invalid; + */ +int set_aes_key(char *key, int len); + +// call this after finish join_link process +void joinlink_deinit(); + +#endif //__JOINLINK_H diff --git a/component/common/application/uart_adapter/uart_adapter.c b/component/common/application/uart_adapter/uart_adapter.c new file mode 100644 index 0000000..314b816 --- /dev/null +++ b/component/common/application/uart_adapter/uart_adapter.c @@ -0,0 +1,2225 @@ +#include "FreeRTOS.h" +#include "task.h" +#include "main.h" +#include +#include +#include +#include "serial_api.h" +#include "serial_ex_api.h" +#include "uart_adapter.h" +#include "wifi_conf.h" +#include "gpio_api.h" // mbed +#include "gpio_irq_api.h" // mbed +#include "osdep_service.h" +#include "flash_api.h" +#include "device_lock.h" +#include +#include +#include + + +/*********************************************************************** + * Macros * + ***********************************************************************/ + +/*********************************************************************** + * Variables Declarations * + ***********************************************************************/ +char ua_tcp_server_ip[16]; + +_Sema ua_exception_sema; +_Sema ua_print_sema; + +int ua_gpio_irq_happen = 0; +int ua_debug_print_en = 0; +int ua_wifi_connected = 0; +int ua_reconnect_started = 0; +int ua_reconnect_ip_change = 0; + +ua_socket_t *ua_global_socket = NULL; +gpio_irq_t gpio_rx_wake; + +/************************************************************************ + * extern variables * + ************************************************************************/ +extern struct netif xnetif[NET_IF_NUM]; + +extern unsigned char psk_essid[NET_IF_NUM][NDIS_802_11_LENGTH_SSID+4]; +extern unsigned char psk_passphrase[NET_IF_NUM][IW_PASSPHRASE_MAX_SIZE + 1]; +extern unsigned char wpa_global_PSK[NET_IF_NUM][A_SHA_DIGEST_LEN * 2]; + +extern wlan_init_done_ptr p_wlan_uart_adapter_callback; +/************************************************************************ + * extern funtions * + ************************************************************************/ +#if CONFIG_INCLUDE_SIMPLE_CONFIG +extern enum sc_result simple_config_test(rtw_network_info_t *); +extern int init_test_data(char *custom_pin_code); +extern void deinit_test_data(void); +extern void filter_add_enable(); +extern void remove_filter(); +extern void wifi_enter_promisc_mode(); +#endif + +/************************************************************************* +* uart releated * +*************************************************************************/ +#define ____________UART__RELATED____________________ +static void uartadapter_uart_irq(uint32_t id, SerialIrq event) +{ + ua_socket_t *ua_socket = (ua_socket_t *)id; + + if(event == RxIrq) { + ua_socket->uart.recv_buf[ua_socket->uart.pwrite++] = serial_getc(&ua_socket->uart.uart_sobj); + RtlUpSemaFromISR(&ua_socket->uart.action_sema); //up action semaphore + + if(ua_socket->uart.pwrite > (UA_UART_RECV_BUFFER_LEN -1)){ //restart from head if reach tail + ua_socket->uart.pwrite = 0; + ua_socket->uart.overlap = 1; + } + + if(ua_socket->uart.overlap && (ua_socket->uart.pwrite > ua_socket->uart.pread) ){ + ua_socket->uart.miss_cnt ++; + ua_socket->uart.pread = ua_socket->uart.pwrite; //if pwrite overhead pread ,pread is always flow rwrite + } + ua_socket->uart.tick_last_update = xTaskGetTickCountFromISR(); // update tick everytime recved data + ua_socket->uart.rx_cnt ++; + } +} + +static int uartadapter_uart_recv_data(ua_socket_t *ua_socket) +{ + int uart_recv_len = 0; + + UA_SOCKET_CHECK_2(ua_socket); + + ua_socket->uart.tick_current = xTaskGetTickCount(); + while((ua_socket->uart.tick_current -ua_socket->uart.tick_last_update) < (UA_UART_MAX_DELAY_TIME/portTICK_RATE_MS) + || ua_socket->uart.tick_current <= ua_socket->uart.tick_last_update){ + if(!ua_socket->uart.overlap){ + uart_recv_len = ua_socket->uart.pwrite - ua_socket->uart.pread; + }else{ + uart_recv_len = (UA_UART_RECV_BUFFER_LEN - ua_socket->uart.pread) + ua_socket->uart.pwrite; + } + + if(uart_recv_len >= UA_UART_FRAME_LEN){ + return 2; + } + //vTaskDelay(10); + ua_socket->uart.tick_current = xTaskGetTickCount(); + } + + return 1; +} + +int uartadapter_uart_read(ua_socket_t *ua_socket, void *read_buf, size_t size) +{ + int ret = 0; + int read_bytes; + int pread_local,pwrite_local; + char *ptr; + + ua_printf(UA_DEBUG, "==>uart adapter read uart"); + + UA_SOCKET_CHECK_2(ua_socket); + + if(!size || !read_buf){ + ua_printf(UA_ERROR, "inpua error,size should not be null"); + ret = -1; + return ret; + } + + pread_local = ua_socket->uart.pread; + pwrite_local = ua_socket->uart.pwrite; + ptr = (char *)read_buf; + + /*calculate how much data not read */ + if(!ua_socket->uart.overlap){ + ua_socket->uart.recv_bytes = pwrite_local - pread_local; + }else{ + ua_socket->uart.recv_bytes = (UA_UART_RECV_BUFFER_LEN - pread_local) + pwrite_local; + } + + /*decide how much data shoule copy to application*/ + if(size >= ua_socket->uart.recv_bytes ){ + read_bytes = ua_socket->uart.recv_bytes; + ret = ua_socket->uart.recv_bytes; + }else{ + read_bytes = size; + ret = size; + } + + if(!ua_socket->uart.overlap){ + memcpy(ptr, (ua_socket->uart.recv_buf+ pread_local), read_bytes ); + }else { + ua_printf(UA_DEBUG, "uart recv buf is write overlap!!"); + if((pread_local + read_bytes) > UA_UART_RECV_BUFFER_LEN){ + memcpy(ptr,(ua_socket->uart.recv_buf+ pread_local),(UA_UART_RECV_BUFFER_LEN-pread_local)); + memcpy(ptr+(UA_UART_RECV_BUFFER_LEN-pread_local), ua_socket->uart.recv_buf,read_bytes-(UA_UART_RECV_BUFFER_LEN- pread_local)); + }else{ + memcpy(ptr,(ua_socket->uart.recv_buf+ pread_local),read_bytes); + } + } + + ua_socket->uart.recv_bytes = 0; + if((pread_local + read_bytes) >= UA_UART_RECV_BUFFER_LEN){ //update pread + ua_socket->uart.pread = (pread_local + read_bytes) - UA_UART_RECV_BUFFER_LEN; + ua_socket->uart.overlap = 0; //clean overlap flags + }else{ + ua_socket->uart.pread = pread_local + read_bytes; + } + + return ret; +} + +int uartadapter_uart_write(ua_socket_t *ua_socket, char *pbuf, size_t size) +{ + int ret = -1; + + UA_SOCKET_CHECK_2(ua_socket); + + if(!size || !pbuf){ + ret = -1; + return ret; + } + + while(RtlDownSema(&ua_socket->uart.dma_tx) == pdTRUE){ + ret = serial_send_stream_dma(&ua_socket->uart.uart_sobj, pbuf, size); + if(ret != HAL_OK){ + ua_printf(UA_ERROR, "uart dma tx error %d!!", ret); + RtlUpSema(&ua_socket->uart.dma_tx); + return -1; + }else{ + return 0; + } + } + + return ret; +} + +void uartadapter_uart_send_stream_done(uint32_t id) +{ + ua_socket_t *ua_socket = (ua_socket_t *)id; + + RtlUpSemaFromISR(&ua_socket->uart.dma_tx); +} + +static void uartadapter_uart_rx_thread(void* param) +{ + ua_socket_t *ua_socket = (ua_socket_t *)param; + char *rxbuf = NULL; + int ret =0; + int read_len = 0; + + UA_SOCKET_CHECK(ua_socket); + + rxbuf = pvPortMalloc(UA_UART_FRAME_LEN); + if(NULL == rxbuf){ + ua_printf(UA_ERROR, "TCP: Allocate rx buffer failed.\n"); + return; + } + + + while(1){ + if(RtlDownSemaWithTimeout(&ua_socket->uart.action_sema, 1000) == pdTRUE){ + ret = uartadapter_uart_recv_data(ua_socket); + if(ret == -1){ + ua_printf(UA_ERROR, "uart recv data error!"); + }else{ + read_len = uartadapter_uart_read(ua_socket, rxbuf, UA_UART_FRAME_LEN); + if(read_len > 0){ + uartadapter_tcp_send_data(ua_socket, rxbuf, read_len); + }else if(read_len < 0){ + ua_printf(UA_ERROR, "tcp send read_len = %d", read_len); + } + } + } +#if UA_PS_ENABLE + else{ + ua_socket->uart.uart_ps_cnt++; + if(ua_socket->uart.uart_ps_cnt >5){ + ua_socket->uart.uart_ps_cnt = 5; + ua_socket->uart.uart_ps = 1; + if(ua_socket->uart.uart_ps && ua_socket->tcp.tcp_ps){ + release_wakelock(UA_WAKELOCK); + } + } + } +#endif + } + +} + +void uartadapter_uart_gpio_wakeup_callback (uint32_t id, gpio_irq_event event) { + acquire_wakelock(UA_WAKELOCK); + ua_socket_t *ua_socket = (ua_socket_t *)id; + ua_socket->uart.uart_ps = 0; + ua_socket->uart.uart_ps_cnt = 0; +} + +int uartadapter_uart_open(ua_socket_t *ua_socket, ua_uart_set_str *puartpara) +{ + PinName uart_tx,uart_rx; + + UA_SOCKET_CHECK_2(ua_socket); + + uart_tx = UA_UART_TX_PIN; + uart_rx = UA_UART_RX_PIN; + ua_socket->uart.uart_param.BaudRate = puartpara->BaudRate; + ua_socket->uart.uart_param.FlowControl = puartpara->FlowControl; + ua_socket->uart.uart_param.WordLen = puartpara->number; + ua_socket->uart.uart_param.Parity = puartpara->parity; + ua_socket->uart.uart_param.StopBit = puartpara->StopBits; + + /*initial uart */ + serial_init(&ua_socket->uart.uart_sobj, uart_tx, uart_rx); + serial_baud(&ua_socket->uart.uart_sobj,puartpara->BaudRate); + serial_format(&ua_socket->uart.uart_sobj, puartpara->number, (SerialParity)puartpara->parity, puartpara->StopBits); + + /*uart irq handle*/ + serial_irq_handler(&ua_socket->uart.uart_sobj, uartadapter_uart_irq, (uint32_t)ua_socket); + serial_irq_set(&ua_socket->uart.uart_sobj, RxIrq, 1); + serial_irq_set(&ua_socket->uart.uart_sobj, TxIrq, 1); + + serial_send_comp_handler(&ua_socket->uart.uart_sobj, (void*)uartadapter_uart_send_stream_done, (uint32_t)ua_socket); + +#if UA_PS_ENABLE + //config uart rx as gpio wakeup pin + gpio_irq_t gpio_rx_wake; + gpio_irq_init(&gpio_rx_wake, UA_GPIO_WAKEUP_PIN, uartadapter_uart_gpio_wakeup_callback, (uint32_t)ua_socket); + gpio_irq_set(&gpio_rx_wake, IRQ_FALL, 1); // Falling Edge Trigger + gpio_irq_enable(&gpio_rx_wake); +#endif + + return 0; +} + +int uartadapter_uart_baud(ua_socket_t *ua_socket, int baud_rate) +{ + int ret = 0; + + UA_SOCKET_CHECK_2(ua_socket); + + ua_socket->uart.uart_param.BaudRate = baud_rate; + + serial_baud(&ua_socket->uart.uart_sobj, baud_rate); + + return ret; +} + +int uartadapter_uart_para(ua_socket_t *ua_socket, int word_len, int parity, int stop_bits) +{ + int ret = 0; + + UA_SOCKET_CHECK_2(ua_socket); + + ua_socket->uart.uart_param.WordLen = word_len; + ua_socket->uart.uart_param.Parity = parity; + ua_socket->uart.uart_param.StopBit = stop_bits; + + serial_format(&ua_socket->uart.uart_sobj, word_len, (SerialParity)parity, stop_bits); + + return ret; +} + +int uartadapter_uart_getpara(ua_socket_t *ua_socket, ua_uart_get_str *uart_para) +{ + UA_SOCKET_CHECK_2(ua_socket); + + uart_para->BaudRate = ua_socket->uart.uart_param.BaudRate; + uart_para->FlowControl = ua_socket->uart.uart_param.FlowControl; + uart_para->number = ua_socket->uart.uart_param.WordLen; + uart_para->parity = ua_socket->uart.uart_param.Parity; + uart_para->StopBits = ua_socket->uart.uart_param.StopBit; + + return 0; +} + +void uartadapter_uart_init(ua_socket_t *ua_socket) +{ + ua_uart_set_str uartset; + ua_uart_get_str uartget; + char uarttest[]="uart0"; + + UA_SOCKET_CHECK(ua_socket); + + uartset.BaudRate = 9600; + uartset.number = 8; + uartset.StopBits = 1; + uartset.FlowControl = 0; + uartset.parity = 0; + strcpy(uartset.UartName,uarttest); + + uartadapter_uart_open(ua_socket, &uartset); + + if(uartadapter_uart_getpara(ua_socket, &uartget)) + ua_printf(UA_ERROR, "get uart failed!"); + else + ua_printf(UA_DEBUG,"uart pata:\r\n"\ + "uart->BaudRate = %d\r\n"\ + "uart->number = %d\r\n"\ + "uart->FlowControl = %d\r\n"\ + "uart->parity = %d\r\n"\ + "uart->StopBits = %d\r\n"\ + "\r\n",\ + uartget.BaudRate,\ + uartget.number,\ + uartget.FlowControl,\ + uartget.parity,\ + uartget.StopBits\ + ); +} + +#define _________FLASH___RELATED________________________ +int uartadapter_flashread(int flashadd, char *pbuf, int len) +{ + int ret = 0; + flash_t flash; + + if( len == 0){ + ua_printf(UA_ERROR, "inpua error,data length should not be null!"); + ret = -1; + return ret; + }else //as 8711am only canbe r/w in words.so make len is 4-bytes aligmented. + len += 4 - ((len%4)==0 ? 4 : (len%4)); + + while(len){ + if(flash_read_word(&flash, flashadd, (unsigned int *)pbuf) !=1 ){ + ua_printf(UA_ERROR, "read flash error!"); + ret = -1; + return ret; + } + len -= 4; + pbuf += 4; + flashadd += 4; + } + + return len; +} + +int uartadapter_flashwrite(int flashadd, char *pbuf, int len) +{ + int ret = 0; + flash_t flash; + + if( len == 0){ + ua_printf(UA_ERROR, "inpua error,data length should not be null!"); + ret = -1; + return ret; + } + else //as 8711am only canbe r/w in words.so make len is 4-bytes aligmented. + len += 4 - ((len%4)==0 ? 4 : (len%4)); + + while(len){ + if(flash_write_word(&flash, flashadd, *(unsigned int *)pbuf) !=1 ){ + ua_printf(UA_ERROR, "write flash error!"); + ret = -1; + return ret; + } + len -= 4; + pbuf += 4; + flashadd += 4; + } + + return ret; +} + +int uartadapter_flasherase(int flashadd, int erase_bytelen) +{ + int ret = 0; + flash_t flash; + device_mutex_lock(RT_DEV_LOCK_FLASH); + flash_erase_sector(&flash, flashadd); + device_mutex_unlock(RT_DEV_LOCK_FLASH); + return ret; +} + +#define _________GPIO___RELATED________________________ +void uartadapter_systemreload(void) +{ + // Cortex-M3 SCB->AIRCR + HAL_WRITE32(0xE000ED00, 0x0C, (0x5FA << 16) | // VECTKEY + (HAL_READ32(0xE000ED00, 0x0C) & (7 << 8)) | // PRIGROUP + (1 << 2)); // SYSRESETREQ +} + +void uartadapter_gpio_irq (uint32_t id, gpio_irq_event event) +{ + ua_printf(UA_DEBUG, "GPIO push button!!"); + + ua_gpio_irq_happen = 1; + RtlUpSemaFromISR(&ua_exception_sema); +} + +void uartadapter_gtimer_timeout_handler(uint32_t id) +{ + gpio_t *gpio_led = (gpio_t *)id; + + gpio_write(gpio_led, !gpio_read(gpio_led)); +} + +void uartadapter_gpio_init(ua_socket_t *ua_socket) +{ + gpio_init(&ua_socket->gpio.gpio_led, UA_GPIO_LED_PIN); + gpio_dir(&ua_socket->gpio.gpio_led, PIN_OUTPUT); // Direction: Output + gpio_mode(&ua_socket->gpio.gpio_led, PullNone); // No pull + + gpio_init(&ua_socket->gpio.gpio_btn, UA_GPIO_IRQ_PIN); + gpio_dir(&ua_socket->gpio.gpio_btn, PIN_INPUT); // Direction: Output + gpio_mode(&ua_socket->gpio.gpio_btn, PullNone); // No pull + + gpio_irq_init(&ua_socket->gpio.gpio_btn_irq, UA_GPIO_IRQ_PIN, uartadapter_gpio_irq, (uint32_t)(&ua_socket->gpio.gpio_btn)); + gpio_irq_set(&ua_socket->gpio.gpio_btn_irq, IRQ_FALL, 1); // Falling Edge Trigger + gpio_irq_enable(&ua_socket->gpio.gpio_btn_irq); + + // Initial a periodical timer + gtimer_init(&ua_socket->gpio.gpio_timer, TIMER0); + //gtimer_start_periodical(&ua_socket->gpio.gpio_timer, 100000, (void*)timer_timeout_handler, (uint32_t)&ua_socket->gpio.gpio_led); +} + +void uartadapter_gpio_led_mode(ua_socket_t *ua_socket, ua_led_mode_t mode) +{ + gtimer_stop(&ua_socket->gpio.gpio_timer); + switch(mode){ + case UART_ADAPTER_LED_ON: + gpio_write(&ua_socket->gpio.gpio_led, 1); + break; + case UART_ADAPTER_LED_OFF: + gpio_write(&ua_socket->gpio.gpio_led, 0); + break; + case UART_ADAPTER_LED_FAST_TWINKLE: + gtimer_start_periodical(&ua_socket->gpio.gpio_timer, 100000, + (void*)uartadapter_gtimer_timeout_handler, (uint32_t)&ua_socket->gpio.gpio_led); + break; + case UART_ADAPTER_LED_SLOW_TWINKLE: + gtimer_start_periodical(&ua_socket->gpio.gpio_timer, 2000000, + (void*)uartadapter_gtimer_timeout_handler, (uint32_t)&ua_socket->gpio.gpio_led); + break; + default: + ua_printf(UA_ERROR, "Unknown GPIO LED mode!!"); + break; + } +} + +#define _________CONTROL__DATA__RELATED________________________ +int uartadapter_strncmp(char *cs, char *ct, size_t count) +{ + unsigned char c1, c2; + + while (count) { + c1 = *cs++; + c2 = *ct++; + if (c1 != c2) + return c1 < c2 ? -1 : 1; + if (!c1) + break; + count--; + } + + return 0; +} + +int uartadapter_control_write_tcp_info_into_flash(ua_socket_t *ua_socket) +{ + int ret; + UA_SOCKET_CHECK_2(ua_socket); + + ua_printf(UA_INFO, "\r\nWrite Uart Adapter tcp connection new profile to flash"); + + uartadapter_flasherase(UA_FAST_RECONNECT_TCP_DATA, 0x1000); + ret = uartadapter_flashwrite(UA_FAST_RECONNECT_TCP_DATA, (char *)&ua_socket->tcp, sizeof(ua_tcp_socket_t)); + return ret; +} + +int uartadapter_control_read_tcp_info_and_connect(ua_socket_t *ua_socket) +{ + int ret = 0; + ua_tcp_socket_t tcp = {0}; + + UA_SOCKET_CHECK_2(ua_socket); + + ua_printf(UA_INFO, "\r\nRead Uart Adapter tcp connection profile from flash"); + + uartadapter_flashread(UA_FAST_RECONNECT_TCP_DATA, (u8*)&tcp, sizeof(ua_tcp_socket_t)); + if(tcp.group_id != ~0x0){ + if(tcp.group_id){ + ua_socket->tcp.group_id = tcp.group_id; + ua_socket->tcp.server_port = tcp.server_port; + ua_socket->tcp.client_port = tcp.client_port; + memcpy(ua_socket->tcp.client_ip, tcp.client_ip, 16); + + if(xTaskCreate(uartadapter_tcp_transmit_server_thread, ((const char*)"tserver"), 256, (void *)ua_socket->tcp.server_port, UA_UART_THREAD_PRIORITY, NULL) != pdPASS) + ua_printf(UA_ERROR, "%s xTaskCreate(tcp server) failed", __FUNCTION__); + + strncpy(ua_tcp_server_ip, ua_socket->tcp.client_ip, 16); + if(xTaskCreate(uartadapter_tcp_transmit_client_forever_thread, ((const char*)"tclient"), 256, (void *)ua_socket->tcp.client_port, UA_UART_THREAD_PRIORITY, NULL) != pdPASS) + ua_printf(UA_ERROR, "%s xTaskCreate(tcp client) failed", __FUNCTION__); + } + } + return 0; +} + +int uartadapter_control_set_req_handle(ua_socket_t *ua_socket, u8 *pbuf, u32 sz) +{ + u8 *p = pbuf; + u8 len = 0; + u16 type = 0; + u32 port = 0; + u32 server_ip = 0; + int ret = 0; + struct sockaddr_in server_addr; + int server_addr_len = sizeof(server_addr); + TXTRecordRef txtRecord; + unsigned char txt_buf[100] = {0}; // use fixed buffer for text record to prevent malloc/free + unsigned char txt_buf2[100] = {0}; // use fixed buffer for text record to prevent malloc/free + + + ua_printf(UA_DEBUG, "\n===>uartadapter_control_set_req_handle()"); + + UA_SOCKET_CHECK_2(ua_socket); + + UA_PRINT_DATA(pbuf, sz); + + while(p < (pbuf+sz)){ + type = (*p)<<8 | *(p+1); + p = p + 2; + len = *p++; + ua_printf(UA_DEBUG, "type=%d len=%d\n", type, len); + switch(type) + { + case UART_CTRL_TYPE_BAUD_RATE: + ua_socket->uart.uart_param.BaudRate = *(u32 *)p; + ua_printf(UA_INFO, "SET UART BAUD_RATE to %d.\n", ua_socket->uart.uart_param.BaudRate); + serial_baud(&ua_socket->uart.uart_sobj, ua_socket->uart.uart_param.BaudRate); + break; + case UART_CTRL_TYPE_WORD_LEN: + ua_socket->uart.uart_param.WordLen = *p; + ua_printf(UA_INFO, "SET UART WORD_LEN to %d.\n", ua_socket->uart.uart_param.WordLen); + serial_format(&ua_socket->uart.uart_sobj, + ua_socket->uart.uart_param.WordLen, + (SerialParity)ua_socket->uart.uart_param.Parity, + ua_socket->uart.uart_param.StopBit); + break; + case UART_CTRL_TYPE_PARITY: + ua_socket->uart.uart_param.Parity = *p; + ua_printf(UA_INFO, "SET UART PARITY to %d.\n", ua_socket->uart.uart_param.Parity); + serial_format(&ua_socket->uart.uart_sobj, + ua_socket->uart.uart_param.WordLen, + (SerialParity)ua_socket->uart.uart_param.Parity, + ua_socket->uart.uart_param.StopBit); + break; + case UART_CTRL_TYPE_STOP_BIT: + ua_socket->uart.uart_param.StopBit = *p; + ua_printf(UA_INFO, "SET UART STOP_BIT to %d.\n", ua_socket->uart.uart_param.StopBit); + serial_format(&ua_socket->uart.uart_sobj, + ua_socket->uart.uart_param.WordLen, + (SerialParity)ua_socket->uart.uart_param.Parity, + ua_socket->uart.uart_param.StopBit); + break; + case UART_CTRL_TYPE_TCP_SERVER_CREATE: + port = (*p)<<8 | *(p+1); + + if(ua_socket->tcp.transmit_server_listen_socket != -1){ + ua_printf(UA_INFO, "Close old transmit server socket %d", ua_socket->tcp.transmit_server_listen_socket); + close(ua_socket->tcp.transmit_server_listen_socket); + } + if(xTaskCreate(uartadapter_tcp_transmit_server_thread, ((const char*)"tserver"), 256, (void *)port, UA_UART_THREAD_PRIORITY, NULL) != pdPASS) + ua_printf(UA_ERROR, "%s xTaskCreate(tcp server) failed", __FUNCTION__); + ua_socket->tcp.server_port = port; + uartadapter_control_write_tcp_info_into_flash(ua_socket); + vTaskDelay(50); + ua_printf(UA_DEBUG, "CREATE TCP SERVER WITH PORT %d.\n", port); + //TODO + break; + case UART_CTRL_TYPE_TCP_SERVER_DELETE: + port = (*p)<<8 | *(p+1); + + if(ua_socket->tcp.transmit_server_listen_socket != -1){ + getsockname (ua_socket->tcp.transmit_server_listen_socket, (struct sockaddr *)&server_addr, &server_addr_len); + if(server_addr.sin_port == ntohs((u16)port)){ + ua_printf(UA_INFO,"uart tcp transmit server socket %d closed by control socket!", ua_socket->tcp.transmit_server_listen_socket); + close(ua_socket->tcp.transmit_server_listen_socket); + ua_socket->tcp.transmit_server_listen_socket = -1; + if(ua_socket->tcp.transmit_recv_socket != -1){ + ua_printf(UA_INFO,"uart tcp transmit receive socket %d closed by control socket!", ua_socket->tcp.transmit_recv_socket); + close(ua_socket->tcp.transmit_recv_socket); + ua_socket->tcp.transmit_recv_socket = -1; + } + + if(ua_socket->tcp.transmit_send_socket != -1){ + ua_printf(UA_INFO,"uart tcp transmit send socket %d closed by control socket!", ua_socket->tcp.transmit_send_socket); + close(ua_socket->tcp.transmit_send_socket); + ua_socket->tcp.transmit_send_socket = -1; + ua_printf(UA_INFO, "DISCONNECT FROM TCP SERVER.\n"); + memset(ua_socket->tcp.client_ip, 0, 16); + ua_socket->tcp.client_port = 0; + } + ua_printf(UA_INFO, "DELETE TCP SERVER \n"); + ua_socket->tcp.server_port = 0; + uartadapter_control_write_tcp_info_into_flash(ua_socket); + }else{ + ua_printf(UA_INFO, "DELETE TCP SERVER FAILED: port not match\n"); + return -1; + } + }else{ + ua_printf(UA_INFO, "DELETE TCP SERVER FAILED: server not exist\n"); + return -1; + } + + break; + case UART_CTRL_TYPE_TCP_CLIENT_CONNECT: + server_ip = (*(p+3))<<24 | (*(p+2))<<16 | (*(p+1))<<8 | *p; + p = p + 4; + memcpy(ua_tcp_server_ip, inet_ntoa(server_ip), 16); + port = (*p)<<8 | *(p+1); + ret = uartadapter_tcpclient(ua_socket, ua_tcp_server_ip, (unsigned short)port); + if(ret == 0){ + ua_printf(UA_INFO, "CONNECT TO TCP SERVER, IP %s PORT %d Success.\n", ua_tcp_server_ip, port); + }else{ + ua_printf(UA_INFO, "CONNECT TO TCP SERVER, IP %s PORT %d Failed.\n", ua_tcp_server_ip, port); + return -1; + } + memcpy(ua_socket->tcp.client_ip, ua_tcp_server_ip, 16); + ua_socket->tcp.client_port = port; + uartadapter_control_write_tcp_info_into_flash(ua_socket); + break; + case UART_CTRL_TYPE_TCP_CLIENT_DISCONNECT: + server_ip = (*(p+3))<<24 | (*(p+2))<<16 | (*(p+1))<<8 | *p; + p = p + 4; + memcpy(ua_tcp_server_ip, inet_ntoa(server_ip), 16); + port = (*p)<<8 | *(p+1); + + if(ua_socket->tcp.transmit_send_socket != -1){ + getpeername(ua_socket->tcp.transmit_send_socket, (struct sockaddr *)&server_addr, &server_addr_len); + if(server_addr.sin_port == ntohs((u16)port) && server_addr.sin_addr.s_addr == server_ip){ + ua_printf(UA_INFO,"uart tcp transmit send socket %d closed by control socket!", ua_socket->tcp.transmit_send_socket); + close(ua_socket->tcp.transmit_send_socket); + ua_socket->tcp.transmit_send_socket = -1; + ua_printf(UA_INFO, "DISCONNECT FROM TCP SERVER.\n"); + memset(ua_socket->tcp.client_ip, 0, 16); + ua_socket->tcp.client_port = 0; + uartadapter_control_write_tcp_info_into_flash(ua_socket); + }else{ + ua_printf(UA_INFO, "DISCONNECT FROM TCP SERVER FAILED: port or IP not match.\n"); + return -1; + } + }else{ + ua_printf(UA_INFO, "DISCONNECT FROM TCP SERVER FAILED: connection not exist\n"); + return -1; + } + break; + case UART_CTRL_TYPE_TCP_GROUP_ID: + ua_socket->tcp.group_id = *p; + ua_printf(UA_INFO,"SET TCP GROUP ID to %d!", *p); + sprintf(txt_buf2, "groupid:%d, tcpserver:%d", ua_socket->tcp.group_id, ua_socket->tcp.server_port); + TXTRecordCreate(&txtRecord, sizeof(txt_buf), txt_buf); + TXTRecordSetValue(&txtRecord, "groupid", strlen(txt_buf2), txt_buf2); + mDNSUpdateService(ua_socket->dnsServiceRef, &txtRecord, 0); + mDNSUpdateService(ua_socket->dnsServiceRef2, &txtRecord, 0); + + uartadapter_control_write_tcp_info_into_flash(ua_socket); + + break; + default: + ua_printf(UA_DEBUG, "Unknown Type, just skip\n"); + break; + + } + p += len; + } + return 0; +} + +int uartadapter_control_get_req_handle(ua_socket_t *ua_socket, u16 type, u8 *prsp, u32 *sz) +{ + u8 *p = prsp; + + ua_printf(UA_DEBUG, "===>uartadapter_control_get_req_handle()"); + + UA_SOCKET_CHECK_2(ua_socket); + + sprintf((char *)p, UA_CONTROL_PREFIX); + p += strlen(UA_CONTROL_PREFIX); + *p++ = UART_CTRL_MODE_GET_RSP; + + if(type & UART_CTRL_TYPE_BAUD_RATE){ + *p++ = 0; + *p++ = UART_CTRL_TYPE_BAUD_RATE; + *p++ = 4; + *(u32*)p = ua_socket->uart.uart_param.BaudRate; + p += 4; + } + if(type & UART_CTRL_TYPE_WORD_LEN){ + *p++ = 0; + *p++ = UART_CTRL_TYPE_WORD_LEN; + *p++ = 1; + *p = ua_socket->uart.uart_param.WordLen; + p += 1; + } + if(type & UART_CTRL_TYPE_PARITY){ + *p++ = 0; + *p++ = UART_CTRL_TYPE_PARITY; + *p++ = 1; + *p = ua_socket->uart.uart_param.Parity; + p += 1; + } + if(type & UART_CTRL_TYPE_STOP_BIT){ + *p++ = 0; + *p++ = UART_CTRL_TYPE_STOP_BIT; + *p++ = 1; + *p = ua_socket->uart.uart_param.StopBit; + p += 1; + } +#if 0 + if(type & UART_CTRL_TYPE_FLOW_CTRL){ + *p++ = UART_CTRL_TYPE_FLOW_CTRL; + *p++ = 1; + *p = ua_socket->uart.uart_param.FlowControl; + p += 1; + } +#endif + *sz = p - prsp; + + UA_PRINT_DATA(prsp, *sz); + return 0; +} + +int uartadapter_control_process(ua_socket_t *ua_socket, char *pbuf, size_t size) +{ + /*the same as socket*/ + int ret = 0; + + UA_SOCKET_CHECK_2(ua_socket); + + if(!size || !pbuf){ + //ua_printf(UA_ERROR, "control data input error,please check!"); + ret = -1; + return ret; + } + + UA_PRINT_DATA(pbuf, size); + + if(uartadapter_strncmp(pbuf, UA_CONTROL_PREFIX, 10) != 0) + { + ua_printf(UA_ERROR, "control data prefix wrong!"); + return -1; + } + else + { + u8 *p = (u8*)pbuf + strlen(UA_CONTROL_PREFIX); + u8 mode = *p++; + switch(mode) + { + case UART_CTRL_MODE_SET_REQ: //AMEBA_UART-MODE-TYPE-LEN-VAL-TYPE-LEN-VAL... + { + char rsp[32] = {0}; //AMEBA_UART-MODE + u32 sz = strlen(UA_CONTROL_PREFIX); + ret = uartadapter_control_set_req_handle(ua_socket, p, (size - strlen(UA_CONTROL_PREFIX) - 1)); + if(0 == ret){ + sprintf(rsp, UA_CONTROL_PREFIX); + *(rsp + sz) = UART_CTRL_MODE_SET_RSP; + sz ++; + sprintf(rsp + sz, "\n"); + sz ++; + vTaskDelay(100); + uartadapter_tcp_send_control(ua_socket, rsp, sz); + } + break; + } + case UART_CTRL_MODE_GET_REQ: //AMEBA_UART-MODE-TYPE + { + char rsp[128] = {0}; + u32 sz = 0; + u16 type = (*p)<<8 | *(p+1); + uartadapter_control_get_req_handle(ua_socket, type, (u8*)rsp, &sz); + sprintf(rsp + sz, "\n"); + sz ++; + vTaskDelay(100); + uartadapter_tcp_send_control(ua_socket, rsp, sz); + break; + } + default: + ua_printf(UA_ERROR, UA_CONTROL_PREFIX": Mode (%d) not support!", mode); + break; + } + } + return 0; +} + +#define _________TCP__RELATED________________________ +int uartadapter_tcpclient(ua_socket_t *ua_socket, const char *host_ip, unsigned short usPort) +{ + int iAddrSize; + int iSockFD = -1; + int iStatus; + int enable = 1; + struct sockaddr_in sAddr; + int send_timeout = 3000; + + UA_SOCKET_CHECK_2(ua_socket); + + FD_ZERO(&sAddr); + sAddr.sin_family = AF_INET; + sAddr.sin_port = htons(usPort); + sAddr.sin_addr.s_addr = inet_addr(host_ip); + + iAddrSize = sizeof(struct sockaddr_in); + + iSockFD = socket(AF_INET, SOCK_STREAM, 0); + if( iSockFD < 0 ) { + ua_printf(UA_ERROR, "TCP ERROR: create tcp client socket fd error!"); + return -1; + } + + ua_printf(UA_DEBUG, "TCP: ServerIP=%s port=%d.", host_ip, usPort); + ua_printf(UA_DEBUG, "TCP: Create socket %d.", iSockFD); + // connecting to TCP server + iStatus = connect(iSockFD, (struct sockaddr *)&sAddr, iAddrSize); + if (iStatus < 0) { + ua_printf(UA_ERROR, "tcp client connect server error %d!", iStatus); + goto Exit; + } + + iStatus = setsockopt(iSockFD, IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(enable)); + if (iStatus < 0) { + ua_printf(UA_ERROR, "tcp client socket set TCP_NODELAY error! "); + goto Exit; + } + + iStatus = setsockopt(iSockFD, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable)); + if (iStatus < 0) { + ua_printf(UA_ERROR, "tcp client socket set SO_KEEPALIVE error! "); + goto Exit; + } + +#if LWIP_SO_SNDTIMEO + iStatus = setsockopt(iSockFD, SOL_SOCKET, SO_SNDTIMEO, &send_timeout, sizeof(int)); + if (iStatus < 0) { + ua_printf(UA_ERROR, "tcp client socket set SO_SNDTIMEO error! "); + goto Exit; + } +#endif + +#if LWIP_SO_RCVTIMEO + iStatus = setsockopt(iSockFD, SOL_SOCKET, SO_RCVTIMEO, &send_timeout, sizeof(int)); + if (iStatus < 0) { + ua_printf(UA_ERROR, "tcp client socket set SO_RCVTIMEO error! "); + goto Exit; + } +#endif + + if(ua_socket->tcp.transmit_send_socket != -1){ + close(ua_socket->tcp.transmit_send_socket); + ua_printf(UA_INFO, "Close old transmit send socket %d.", ua_socket->tcp.transmit_send_socket); + } + + ua_printf(UA_INFO, "Connect to transmit server successfully."); + ua_socket->tcp.transmit_send_socket = iSockFD; + + return 0; + +Exit: + close(iSockFD); + return -1; +} + +int uartadapter_tcpserver(ua_socket_t *ua_socket, unsigned short usPort, u8 socket_type) +{ + struct sockaddr_in sLocalAddr; + int iAddrSize; + int iSockFD; + int iStatus; + int enable = 1; + + UA_SOCKET_CHECK_2(ua_socket); + + iSockFD = socket(AF_INET, SOCK_STREAM, 0); + if( iSockFD < 0 ) { + ua_printf(UA_ERROR, "create server_socket error!"); + goto Exit; + } + + iStatus = setsockopt( iSockFD, SOL_SOCKET, SO_REUSEADDR, + (const char *) &enable, sizeof( enable ) ); + if( iStatus < 0 ) { + ua_printf(UA_ERROR, "set tcp server socket SO_REUSEADDR error %d! ", iStatus); + goto Exit; + } + + ua_printf(UA_DEBUG, "TCP: Create Tcp server socket %d", iSockFD); + + //filling the TCP server socket address + memset((char *)&sLocalAddr, 0, sizeof(sLocalAddr)); + sLocalAddr.sin_family = AF_INET; + sLocalAddr.sin_len = sizeof(sLocalAddr); + sLocalAddr.sin_port = htons(usPort); + sLocalAddr.sin_addr.s_addr = htonl(INADDR_ANY); + + iAddrSize = sizeof(sLocalAddr); + + iStatus = bind(iSockFD, (struct sockaddr *)&sLocalAddr, iAddrSize); + if( iStatus < 0 ) { + ua_printf(UA_ERROR, "bind tcp server socket fd error %d! ", iStatus); + goto Exit; + } + ua_printf(UA_DEBUG, "TCP: Bind successfully."); + + iStatus = listen(iSockFD, 10); + if( iStatus != 0 ) { + ua_printf(UA_ERROR, "listen tcp server socket fd error %d!", iStatus); + goto Exit; + } + + if(0 == socket_type){ + ua_socket->tcp.chat_server_listen_socket = iSockFD; + ua_printf(UA_INFO, "TCP Chat Server: Listen on port %d", usPort); + }else if(1 == socket_type){ + ua_socket->tcp.control_server_listen_socket = iSockFD; + ua_printf(UA_INFO, "TCP Control Server: Listen on port %d", usPort); + }else{ + ua_socket->tcp.transmit_server_listen_socket = iSockFD; + ua_printf(UA_INFO, "TCP Transmit Server: Listen on port %d", usPort); + } + + return 0; + +Exit: + close(iSockFD); + ua_printf(UA_DEBUG, "Tcp server listen on port %d closed!", usPort); + return 0; +} + +void uartadapter_tcp_chat_server_thread(void *param) +{ + ua_socket_t *ua_socket = (ua_socket_t *)param; + unsigned short port = UA_CHAT_SOCKET_PORT; + + UA_SOCKET_CHECK(ua_socket); + + ua_printf(UA_DEBUG, "Uart Adapter: Start Tcp Data Server!"); + uartadapter_tcpserver(ua_socket, port, 0); + +#if defined(INCLUDE_uxTaskGetStackHighWaterMark) && (INCLUDE_uxTaskGetStackHighWaterMark == 1) + ua_printf(UA_DEBUG, "Min available stack size of %s = %d * %d bytes\n\r", __FUNCTION__, uxTaskGetStackHighWaterMark(NULL), sizeof(portBASE_TYPE)); +#endif + ua_printf(UA_DEBUG, "TCP: Tcp data server stopped!"); + vTaskDelete(NULL); +} + +void uartadapter_tcp_control_server_thread(void *param) +{ + ua_socket_t *ua_socket = (ua_socket_t *)param; + unsigned short port = UA_CONTROL_SOCKET_PORT; + + UA_SOCKET_CHECK(ua_socket); + + ua_printf(UA_DEBUG, "Uart Adapter: Start Tcp Control Server!"); + uartadapter_tcpserver(ua_socket, port, 1); + +#if defined(INCLUDE_uxTaskGetStackHighWaterMark) && (INCLUDE_uxTaskGetStackHighWaterMark == 1) + ua_printf(UA_DEBUG, "Min available stack size of %s = %d * %d bytes", __FUNCTION__, uxTaskGetStackHighWaterMark(NULL), sizeof(portBASE_TYPE)); +#endif + ua_printf(UA_DEBUG, "TCP: Tcp control server stopped!"); + vTaskDelete(NULL); +} + +void uartadapter_tcp_transmit_server_thread(void *param) +{ + ua_socket_t *ua_socket = ua_global_socket; + unsigned short port = (int)param; + + UA_SOCKET_CHECK(ua_socket); + + ua_printf(UA_DEBUG, "Uart Adapter: Start Tcp Transmit Server!"); + uartadapter_tcpserver(ua_socket, port, 2); + + uartadapter_gpio_led_mode(ua_socket, UART_ADAPTER_LED_SLOW_TWINKLE); + +#if defined(INCLUDE_uxTaskGetStackHighWaterMark) && (INCLUDE_uxTaskGetStackHighWaterMark == 1) + ua_printf(UA_DEBUG, "Min available stack size of %s = %d * %d bytes", __FUNCTION__, uxTaskGetStackHighWaterMark(NULL), sizeof(portBASE_TYPE)); +#endif + ua_printf(UA_DEBUG, "TCP: Tcp transmit server thread delete!"); + vTaskDelete(NULL); +} + +void uartadapter_tcp_transmit_client_thread(void *param) +{ + ua_socket_t *ua_socket = ua_global_socket; + unsigned short port = (int)param; + + UA_SOCKET_CHECK(ua_socket); + + ua_printf(UA_DEBUG, "Uart Adapter: Start Tcp Data Client!"); + uartadapter_tcpclient(ua_socket, ua_tcp_server_ip, port); + + uartadapter_gpio_led_mode(ua_socket, UART_ADAPTER_LED_SLOW_TWINKLE); + +#if defined(INCLUDE_uxTaskGetStackHighWaterMark) && (INCLUDE_uxTaskGetStackHighWaterMark == 1) + ua_printf(UA_DEBUG, "Min available stack size of %s = %d * %d bytes\n\r", __FUNCTION__, uxTaskGetStackHighWaterMark(NULL), sizeof(portBASE_TYPE)); +#endif + ua_printf(UA_DEBUG, "TCP: Tcp transmit client thread delete!"); + vTaskDelete(NULL); +} + +void uartadapter_tcp_transmit_client_forever_thread(void *param) +{ + ua_socket_t *ua_socket = ua_global_socket; + unsigned short port = (int)param; + int ret = 0; + UA_SOCKET_CHECK(ua_socket); + + ua_printf(UA_DEBUG, "Uart Adapter: Start Tcp Transmit Client forever thread!"); + + do{ + ret = uartadapter_tcpclient(ua_socket, ua_tcp_server_ip, port); + if(ret != 0){ + ua_printf(UA_INFO, "Uart Adapter: Try to connect to TCP server again"); + vTaskDelay(3000); + } + }while(ret != 0); + + uartadapter_gpio_led_mode(ua_socket, UART_ADAPTER_LED_SLOW_TWINKLE); + +#if defined(INCLUDE_uxTaskGetStackHighWaterMark) && (INCLUDE_uxTaskGetStackHighWaterMark == 1) + ua_printf(UA_DEBUG, "Min available stack size of %s = %d * %d bytes\n\r", __FUNCTION__, uxTaskGetStackHighWaterMark(NULL), sizeof(portBASE_TYPE)); +#endif + ua_printf(UA_DEBUG, "TCP: Tcp transmit client thread delete!"); + vTaskDelete(NULL); +} + +void uartadapter_tcp_send_data(ua_socket_t *ua_socket, char *buffer, int size) +{ + int iStatus; + + UA_SOCKET_CHECK(ua_socket); + + if(ua_socket->tcp.chat_socket != -1){ + ua_socket->tcp.send_flag = 1; + RtlDownSema(&ua_socket->uart.tcp_tx_rx_sema); + iStatus = send(ua_socket->tcp.chat_socket, buffer, size, 0 ); + RtlUpSema(&ua_socket->uart.tcp_tx_rx_sema); + ua_socket->tcp.send_flag = 0; + if( iStatus <= 0 ){ + ua_printf(UA_ERROR, "tcp chat socket send data error! iStatus:%d!", iStatus); + }else{ + ua_socket->tcp.tx_cnt += iStatus; + } + } + + if(ua_socket->tcp.transmit_send_socket != -1){ + ua_socket->tcp.send_flag = 1; + iStatus = send(ua_socket->tcp.transmit_send_socket, buffer, size, 0 ); + ua_socket->tcp.send_flag = 0; + if( iStatus <= 0 ){ + ua_printf(UA_ERROR, "tcp transmit send socket send data error! iStatus:%d!", iStatus); + }else{ + ua_socket->tcp.tx_cnt += iStatus; + } + } + + return; +} + +void uartadapter_tcp_send_control(ua_socket_t *ua_socket, char *buffer, int size) +{ + int iStatus; + + UA_SOCKET_CHECK(ua_socket); + + if(ua_socket->tcp.control_socket != -1){ + ua_socket->tcp.send_flag = 1; + iStatus = send(ua_socket->tcp.control_socket, buffer, size, 0 ); + ua_socket->tcp.send_flag = 0; + if( iStatus <= 0 ){ + ua_printf(UA_ERROR,"tcp control socket send data error! iStatus:%d!", iStatus); + } + + if(ua_debug_print_en){ + ua_printf(UA_INFO,"uart tcp control socket send %d bytes, ret %d!", size, iStatus); + } + } + + return; +} + +void uartadapter_tcp_except_handler(ua_socket_t *ua_socket, fd_set *exceptfds) +{ + if(ua_socket->tcp.chat_socket != -1 && FD_ISSET(ua_socket->tcp.chat_socket, exceptfds)){ + ua_printf(UA_INFO,"uart tcp chat socket %d exception happen, need to close!", ua_socket->tcp.chat_socket); + close(ua_socket->tcp.chat_socket); + ua_socket->tcp.chat_socket = -1; + } + + if(ua_socket->tcp.control_socket != -1 && FD_ISSET(ua_socket->tcp.control_socket, exceptfds)){ + ua_printf(UA_INFO,"uart tcp control socket %d exception happen, need to close!", ua_socket->tcp.control_socket); + close(ua_socket->tcp.control_socket); + ua_socket->tcp.control_socket = -1; + } + + if(ua_socket->tcp.transmit_recv_socket != -1 && FD_ISSET(ua_socket->tcp.transmit_recv_socket, exceptfds)){ + ua_printf(UA_INFO,"uart tcp transmit recv socket %d exception happen, need to close!", ua_socket->tcp.transmit_recv_socket); + close(ua_socket->tcp.transmit_recv_socket); + ua_socket->tcp.transmit_recv_socket = -1; + uartadapter_gpio_led_mode(ua_socket, UART_ADAPTER_LED_FAST_TWINKLE); +#if 0 + if(ua_socket->tcp.transmit_server_listen_socket != -1){ + ua_printf(UA_INFO,"uart tcp transmit server socket %d exception happen, need to close!", ua_socket->tcp.transmit_server_listen_socket); + close(ua_socket->tcp.transmit_server_listen_socket); + ua_socket->tcp.transmit_server_listen_socket = -1; + } +#endif + } + + if(ua_socket->tcp.transmit_send_socket != -1 && FD_ISSET(ua_socket->tcp.transmit_send_socket, exceptfds)){ + ua_printf(UA_INFO,"uart tcp transmit send socket %d exception happen, need to close!", ua_socket->tcp.transmit_send_socket); + close(ua_socket->tcp.transmit_send_socket); + ua_socket->tcp.transmit_send_socket = -1; + uartadapter_gpio_led_mode(ua_socket, UART_ADAPTER_LED_FAST_TWINKLE); + + strncpy(ua_tcp_server_ip, ua_socket->tcp.client_ip, 16); + if(xTaskCreate(uartadapter_tcp_transmit_client_forever_thread, ((const char*)"tclient"), 256, (void *)ua_socket->tcp.client_port, UA_UART_THREAD_PRIORITY, NULL) != pdPASS) + ua_printf(UA_ERROR, "%s xTaskCreate(tcp client) failed", __FUNCTION__); + } + + if(ua_socket->tcp.chat_server_listen_socket != -1 && FD_ISSET(ua_socket->tcp.chat_server_listen_socket, exceptfds)){ + ua_printf(UA_INFO,"uart tcp chat server socket %d exception happen, need to restart!", ua_socket->tcp.chat_server_listen_socket); + close(ua_socket->tcp.chat_server_listen_socket); + ua_socket->tcp.chat_server_listen_socket = -1; + uartadapter_tcpserver(ua_socket, UA_CHAT_SOCKET_PORT, 0); + } + + if(ua_socket->tcp.control_server_listen_socket != -1 && FD_ISSET(ua_socket->tcp.control_server_listen_socket, exceptfds)){ + ua_printf(UA_INFO,"uart tcp control server socket %d exception happen, need to restart!", ua_socket->tcp.control_server_listen_socket); + close(ua_socket->tcp.control_server_listen_socket); + ua_socket->tcp.control_server_listen_socket = -1; + uartadapter_tcpserver(ua_socket, UA_CONTROL_SOCKET_PORT, 1); + } + + if(ua_socket->tcp.transmit_server_listen_socket != -1 && FD_ISSET(ua_socket->tcp.transmit_server_listen_socket, exceptfds)){ + ua_printf(UA_INFO,"uart tcp transmit server socket %d exception happen, need to close!", ua_socket->tcp.transmit_server_listen_socket); + close(ua_socket->tcp.transmit_server_listen_socket); + ua_socket->tcp.transmit_server_listen_socket = -1; + //uartadapter_gpio_led_mode(ua_socket, UART_ADAPTER_LED_FAST_TWINKLE); + uartadapter_tcpserver(ua_socket, ua_socket->tcp.server_port, 2); + } + +} + +void uartadapter_tcp_chat_socket_handler(ua_socket_t *ua_socket, char *tcp_rxbuf) +{ + int recv_len; + + UA_SOCKET_CHECK(ua_socket); + + ua_socket->tcp.recv_flag = 1; + RtlDownSema(&ua_socket->uart.tcp_tx_rx_sema); + recv_len = recv(ua_socket->tcp.chat_socket, tcp_rxbuf, UA_UART_FRAME_LEN, MSG_DONTWAIT); + RtlUpSema(&ua_socket->uart.tcp_tx_rx_sema); + ua_socket->tcp.recv_flag = 0; + if(recv_len < 0){ + ua_printf(UA_ERROR, "Tcp Chat Socket %d Recv Error, ret = %d", ua_socket->tcp.chat_socket, recv_len); + }else if(recv_len == 0){ + ua_printf(UA_INFO, "Tcp Chat Socket %d closed", ua_socket->tcp.chat_socket); + close(ua_socket->tcp.chat_socket); + ua_socket->tcp.chat_socket = -1; + }else{ + ua_printf(UA_DEBUG, "Tcp Chat Socket %d Recv %d Data", ua_socket->tcp.chat_socket, recv_len); + uartadapter_uart_write(ua_socket, tcp_rxbuf, recv_len); + ua_socket->tcp.rx_cnt += recv_len; + } + + return; +} + +void uartadapter_tcp_control_socket_handler(ua_socket_t *ua_socket) +{ + char tcp_rxbuf[UA_UART_FRAME_LEN]; + int recv_len; + + UA_SOCKET_CHECK(ua_socket); + + recv_len = recv(ua_socket->tcp.control_socket, tcp_rxbuf, UA_UART_FRAME_LEN, MSG_DONTWAIT); //MSG_DONTWAIT MSG_WAITALL + if(recv_len<0){ + ua_printf(UA_ERROR, "Tcp Control Socket %d Recv Error", ua_socket->tcp.control_socket); + }else if(recv_len == 0){ + ua_printf(UA_INFO, "Tcp Control Socket %d closed", ua_socket->tcp.control_socket); + close(ua_socket->tcp.control_socket); + ua_socket->tcp.control_socket = -1; + }else{ + ua_printf(UA_DEBUG, "Tcp Control Socket %d Recv %d Data", ua_socket->tcp.control_socket, recv_len); + uartadapter_control_process(ua_socket, (void*)tcp_rxbuf, recv_len); + } + + return; +} + +void uartadapter_tcp_transmit_socket_handler(ua_socket_t *ua_socket, char *tcp_rxbuf) +{ + int recv_len; + + UA_SOCKET_CHECK(ua_socket); + + ua_socket->tcp.recv_flag = 1; + recv_len = recv(ua_socket->tcp.transmit_recv_socket, tcp_rxbuf, UA_UART_FRAME_LEN, MSG_DONTWAIT); + ua_socket->tcp.recv_flag = 0; + if(recv_len < 0){ + ua_printf(UA_ERROR, "Tcp Transmit Recv Socket %d Recv Error, ret = %d", ua_socket->tcp.transmit_recv_socket, recv_len); + }else if(recv_len == 0){ + ua_printf(UA_INFO, "Tcp Transmit Recv Socket %d closed", ua_socket->tcp.transmit_recv_socket); + close(ua_socket->tcp.transmit_recv_socket); + ua_socket->tcp.transmit_recv_socket = -1; +#if 0 + if(ua_socket->tcp.transmit_server_listen_socket != -1){ + ua_printf(UA_INFO, "Tcp Transmit Server Socket %d closed", ua_socket->tcp.transmit_server_listen_socket); + close(ua_socket->tcp.transmit_server_listen_socket); + ua_socket->tcp.transmit_server_listen_socket = -1; + } +#endif + }else{ + uartadapter_uart_write(ua_socket, tcp_rxbuf, recv_len); + ua_socket->tcp.rx_cnt += recv_len; + } + + return; +} + +void uartadapter_tcp_chat_listen_socket_handler(ua_socket_t *ua_socket) +{ + int old_chat_socket; + struct sockaddr_in sAddr; + int addrlen = sizeof(sAddr); + int iStatus; + int enable = 1; + int send_timeout = 3000; + + UA_SOCKET_CHECK(ua_socket); + + old_chat_socket = ua_socket->tcp.chat_socket; + + ua_socket->tcp.chat_socket = accept(ua_socket->tcp.chat_server_listen_socket, (struct sockaddr *)&sAddr, (socklen_t*)&addrlen); + if( ua_socket->tcp.chat_socket< 0 ) { + ua_printf(UA_ERROR, "Accept tcp chat socket error"); + goto EXIT; + } + + iStatus = setsockopt(ua_socket->tcp.chat_socket, IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(enable)); + if (iStatus < 0) { + ua_printf(UA_ERROR, "tcp chat socket set opt TCP_NODELAY error! "); + goto EXIT; + } + + iStatus = setsockopt(ua_socket->tcp.chat_socket, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable)); + if (iStatus < 0) { + ua_printf(UA_ERROR, "tcp chat socket set opt SO_KEEPALIVE error! "); + goto EXIT; + } + +#if LWIP_SO_SNDTIMEO + iStatus = setsockopt(ua_socket->tcp.chat_socket, SOL_SOCKET, SO_SNDTIMEO, &send_timeout, sizeof(send_timeout)); + if (iStatus < 0) { + ua_printf(UA_ERROR, "tcp client socket set opt error! "); + goto EXIT; + } +#endif + +#if LWIP_SO_RCVTIMEO + iStatus = setsockopt(ua_socket->tcp.chat_socket, SOL_SOCKET, SO_RCVTIMEO, &send_timeout, sizeof(send_timeout)); + if (iStatus < 0) { + ua_printf(UA_ERROR, "tcp client socket set opt error! "); + goto EXIT; + } +#endif + + ua_printf(UA_INFO, "Accept new chat socket %d on port %d successfully.", ua_socket->tcp.chat_socket, htons(sAddr.sin_port)); + if(old_chat_socket != -1) + { + close(old_chat_socket); + ua_printf(UA_INFO, "Close old chat socket %d.", old_chat_socket); + } + + return; + +EXIT: + if(ua_socket->tcp.chat_server_listen_socket != -1){ + close(ua_socket->tcp.chat_server_listen_socket); + ua_socket->tcp.chat_server_listen_socket = -1; + } +} + +void uartadapter_tcp_control_listen_socket_handler(ua_socket_t *ua_socket) +{ + int old_control_socket; + struct sockaddr_in sAddr; + int addrlen = sizeof(sAddr); + int iStatus; + int enable = 1; + int send_timeout = 3000; + + UA_SOCKET_CHECK(ua_socket); + + old_control_socket = ua_socket->tcp.control_socket; + + ua_socket->tcp.control_socket = accept(ua_socket->tcp.control_server_listen_socket, (struct sockaddr *)&sAddr, (socklen_t*)&addrlen); + if( ua_socket->tcp.control_socket< 0 ) { + ua_printf(UA_ERROR, "Accept tcp control socket error"); + goto EXIT; + } + + iStatus = setsockopt(ua_socket->tcp.control_socket, IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(enable)); + if (iStatus < 0) { + ua_printf(UA_ERROR, "tcp chat socket set opt TCP_NODELAY error! "); + goto EXIT; + } + + iStatus = setsockopt(ua_socket->tcp.control_socket, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable)); + if (iStatus < 0) { + ua_printf(UA_ERROR, "tcp chat socket set opt SO_KEEPALIVE error! "); + goto EXIT; + } + +#if LWIP_SO_SNDTIMEO + iStatus = setsockopt(ua_socket->tcp.control_socket, SOL_SOCKET, SO_SNDTIMEO, &send_timeout, sizeof(send_timeout)); + if (iStatus < 0) { + ua_printf(UA_ERROR, "tcp client socket set opt error! "); + goto EXIT; + } +#endif + +#if LWIP_SO_RCVTIMEO + iStatus = setsockopt(ua_socket->tcp.control_socket, SOL_SOCKET, SO_RCVTIMEO, &send_timeout, sizeof(send_timeout)); + if (iStatus < 0) { + ua_printf(UA_ERROR, "tcp client socket set opt error! "); + goto EXIT; + } +#endif + + ua_printf(UA_INFO, "Accept new control socket %d on port %d successfully.", ua_socket->tcp.control_socket, htons(sAddr.sin_port)); + if(old_control_socket != -1) + { + close(old_control_socket); + ua_printf(UA_INFO, "Close old control socket %d.", old_control_socket); + } + + return; + +EXIT: + if(ua_socket->tcp.control_server_listen_socket!= -1){ + close(ua_socket->tcp.control_server_listen_socket); + ua_socket->tcp.control_server_listen_socket= -1; + } +} + +void uartadapter_tcp_transmit_listen_socket_handler(ua_socket_t *ua_socket) +{ + int old_transmit_recv_socket; + struct sockaddr_in sAddr; + int addrlen = sizeof(sAddr); + int iStatus; + int enable = 1; + int send_timeout = 3000; + + UA_SOCKET_CHECK(ua_socket); + + old_transmit_recv_socket = ua_socket->tcp.transmit_recv_socket; + + ua_socket->tcp.transmit_recv_socket = accept(ua_socket->tcp.transmit_server_listen_socket, (struct sockaddr *)&sAddr, (socklen_t*)&addrlen); + if( ua_socket->tcp.transmit_recv_socket < 0 ) { + ua_printf(UA_ERROR, "Accept tcp control socket error"); + goto EXIT; + } + + iStatus = setsockopt(ua_socket->tcp.transmit_recv_socket, IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(enable)); + if (iStatus < 0) { + ua_printf(UA_ERROR, "tcp transmit recv socket set opt TCP_NODELAY error! "); + goto EXIT; + } + + iStatus = setsockopt(ua_socket->tcp.transmit_recv_socket, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable)); + if (iStatus < 0) { + ua_printf(UA_ERROR, "tcp transmit recv socket set opt SO_KEEPALIVE error! "); + goto EXIT; + } + +#if LWIP_SO_SNDTIMEO + iStatus = setsockopt(ua_socket->tcp.transmit_recv_socket, SOL_SOCKET, SO_SNDTIMEO, &send_timeout, sizeof(send_timeout)); + if (iStatus < 0) { + ua_printf(UA_ERROR, "tcp client socket set opt error! "); + goto EXIT; + } +#endif + +#if LWIP_SO_RCVTIMEO + iStatus = setsockopt(ua_socket->tcp.transmit_recv_socket, SOL_SOCKET, SO_RCVTIMEO, &send_timeout, sizeof(send_timeout)); + if (iStatus < 0) { + ua_printf(UA_ERROR, "tcp client socket set opt error! "); + goto EXIT; + } +#endif + + ua_printf(UA_INFO, "Accept new transmit recv socket %d on port %d successfully.", ua_socket->tcp.transmit_recv_socket, htons(sAddr.sin_port)); + if(old_transmit_recv_socket != -1) + { + close(old_transmit_recv_socket); + ua_printf(UA_INFO, "Close old transmit recv socket %d.", old_transmit_recv_socket); + } + + return; + +EXIT: + if(ua_socket->tcp.transmit_server_listen_socket!= -1){ + close(ua_socket->tcp.transmit_server_listen_socket); + ua_socket->tcp.transmit_server_listen_socket= -1; + } +} + +void uartadapter_tcp_select_restart_handler(ua_socket_t *ua_socket) +{ + if(ua_socket->tcp.chat_socket != -1){ + ua_printf(UA_INFO,"IP changed, uart tcp chat socket %d need to close!", ua_socket->tcp.chat_socket); + close(ua_socket->tcp.chat_socket); + ua_socket->tcp.chat_socket = -1; + } + + if(ua_socket->tcp.control_socket != -1){ + ua_printf(UA_INFO,"IP changed, uart tcp control socket %d need to close!", ua_socket->tcp.control_socket); + close(ua_socket->tcp.control_socket); + ua_socket->tcp.control_socket = -1; + } + + if(ua_socket->tcp.transmit_recv_socket != -1){ + ua_printf(UA_INFO,"IP changed, uart tcp transmit recv socket %d need to close!", ua_socket->tcp.transmit_recv_socket); + close(ua_socket->tcp.transmit_recv_socket); + ua_socket->tcp.transmit_recv_socket = -1; + uartadapter_gpio_led_mode(ua_socket, UART_ADAPTER_LED_FAST_TWINKLE); + } + + if(ua_socket->tcp.transmit_send_socket != -1){ + ua_printf(UA_INFO,"IP changed, uart tcp transmit send socket %d need to close!", ua_socket->tcp.transmit_send_socket); + close(ua_socket->tcp.transmit_send_socket); + ua_socket->tcp.transmit_send_socket = -1; + uartadapter_gpio_led_mode(ua_socket, UART_ADAPTER_LED_FAST_TWINKLE); + } + + if(ua_socket->tcp.chat_server_listen_socket!= -1){ + ua_printf(UA_INFO,"IP changed, uart tcp chat server socket %d need to restart!", ua_socket->tcp.chat_server_listen_socket); + close(ua_socket->tcp.chat_server_listen_socket); + ua_socket->tcp.chat_server_listen_socket = -1; + uartadapter_tcpserver(ua_socket, UA_CHAT_SOCKET_PORT, 0); + } + + if(ua_socket->tcp.control_server_listen_socket!= -1){ + ua_printf(UA_INFO,"IP changed, uart tcp control server socket %d need to restart!", ua_socket->tcp.control_server_listen_socket); + close(ua_socket->tcp.control_server_listen_socket); + ua_socket->tcp.control_server_listen_socket = -1; + uartadapter_tcpserver(ua_socket, UA_CONTROL_SOCKET_PORT, 1); + } + + if(ua_socket->tcp.transmit_server_listen_socket!= -1){ + ua_printf(UA_INFO,"IP changed, uart tcp transmit server socket %d need to close!", ua_socket->tcp.transmit_server_listen_socket); + close(ua_socket->tcp.transmit_server_listen_socket); + ua_socket->tcp.transmit_server_listen_socket = -1; + uartadapter_gpio_led_mode(ua_socket, UART_ADAPTER_LED_FAST_TWINKLE); + } + +} + +void uartadapter_tcp_select_thread(void *param) +{ + ua_socket_t *ua_socket = (ua_socket_t *)param; + int max_fd; + struct timeval tv; + fd_set readfds; + fd_set exceptfds; + int ret = 0; + char *tcp_rxbuf; + + UA_SOCKET_CHECK(ua_socket); + + tcp_rxbuf = pvPortMalloc(UA_UART_FRAME_LEN); + if(NULL == tcp_rxbuf){ + ua_printf(UA_ERROR, "Allocate select buffer failed.\n"); + return; + } + + while(1){ + if(ua_reconnect_ip_change){ + uartadapter_tcp_select_restart_handler(ua_socket); + ua_reconnect_ip_change = 0; + } + + FD_ZERO(&readfds); + FD_ZERO(&exceptfds); + max_fd = -1; + + if(ua_socket->tcp.chat_socket != -1){ + FD_SET(ua_socket->tcp.chat_socket, &readfds); + FD_SET(ua_socket->tcp.chat_socket, &exceptfds); + if(ua_socket->tcp.chat_socket > max_fd) + max_fd = ua_socket->tcp.chat_socket; + } + + if(ua_socket->tcp.control_socket != -1){ + FD_SET(ua_socket->tcp.control_socket, &readfds); + FD_SET(ua_socket->tcp.control_socket, &exceptfds); + if(ua_socket->tcp.control_socket > max_fd) + max_fd = ua_socket->tcp.control_socket; + } + + if(ua_socket->tcp.control_server_listen_socket != -1){ + FD_SET(ua_socket->tcp.control_server_listen_socket, &readfds); + FD_SET(ua_socket->tcp.control_server_listen_socket, &exceptfds); + if(ua_socket->tcp.control_server_listen_socket > max_fd) + max_fd = ua_socket->tcp.control_server_listen_socket; + } + + if(ua_socket->tcp.chat_server_listen_socket != -1){ + FD_SET(ua_socket->tcp.chat_server_listen_socket, &readfds); + FD_SET(ua_socket->tcp.chat_server_listen_socket, &exceptfds); + if(ua_socket->tcp.chat_server_listen_socket > max_fd) + max_fd = ua_socket->tcp.chat_server_listen_socket; + } + + if(ua_socket->tcp.transmit_recv_socket != -1){ + FD_SET(ua_socket->tcp.transmit_recv_socket, &readfds); + FD_SET(ua_socket->tcp.transmit_recv_socket, &exceptfds); + if(ua_socket->tcp.transmit_recv_socket > max_fd) + max_fd = ua_socket->tcp.transmit_recv_socket; + } + + if(ua_socket->tcp.transmit_send_socket != -1){ + FD_SET(ua_socket->tcp.transmit_send_socket, &exceptfds); + if(ua_socket->tcp.transmit_send_socket > max_fd) + max_fd = ua_socket->tcp.transmit_send_socket; + } + + if(ua_socket->tcp.transmit_server_listen_socket != -1){ + FD_SET(ua_socket->tcp.transmit_server_listen_socket, &readfds); + FD_SET(ua_socket->tcp.transmit_server_listen_socket, &exceptfds); + if(ua_socket->tcp.transmit_server_listen_socket> max_fd) + max_fd = ua_socket->tcp.transmit_server_listen_socket; + } + + tv.tv_sec = 1; + tv.tv_usec = 0; + + ret = select(max_fd + 1, &readfds, NULL, &exceptfds, &tv); + + if(ua_debug_print_en){ + ua_printf(UA_INFO, "uart adapter test select ret = %x",ret); + } + if(ret > 0){ +#if UA_PS_ENABLE + //printf("select get lock \r\n"); + acquire_wakelock(UA_WAKELOCK); + ua_socket->tcp.tcp_ps = 0; + ua_socket->tcp.tcp_ps_cnt = 0; +#endif + + uartadapter_tcp_except_handler(ua_socket, &exceptfds); + + if(ua_socket->tcp.chat_socket != -1 && FD_ISSET(ua_socket->tcp.chat_socket, &readfds)){ + uartadapter_tcp_chat_socket_handler(ua_socket, tcp_rxbuf); + } + + if(ua_socket->tcp.control_socket != -1 && FD_ISSET(ua_socket->tcp.control_socket, &readfds)){ + uartadapter_tcp_control_socket_handler(ua_socket); + } + + if(ua_socket->tcp.transmit_recv_socket != -1 && FD_ISSET(ua_socket->tcp.transmit_recv_socket, &readfds)){ + uartadapter_tcp_transmit_socket_handler(ua_socket, tcp_rxbuf); + } + + if(ua_socket->tcp.chat_server_listen_socket!= -1 && FD_ISSET(ua_socket->tcp.chat_server_listen_socket, &readfds)){ + uartadapter_tcp_chat_listen_socket_handler(ua_socket); + } + + if(ua_socket->tcp.control_server_listen_socket!= -1 && FD_ISSET(ua_socket->tcp.control_server_listen_socket, &readfds)){ + uartadapter_tcp_control_listen_socket_handler(ua_socket); + } + + if(ua_socket->tcp.transmit_server_listen_socket!= -1 && FD_ISSET(ua_socket->tcp.transmit_server_listen_socket, &readfds)){ + uartadapter_tcp_transmit_listen_socket_handler(ua_socket); + } + + + } +#if UA_PS_ENABLE + else{ + ua_socket->tcp.tcp_ps_cnt++; + if(ua_socket->tcp.tcp_ps_cnt > 5){ + ua_socket->tcp.tcp_ps_cnt = 5; + ua_socket->tcp.tcp_ps = 1; + if(ua_socket->uart.uart_ps && ua_socket->tcp.tcp_ps){ + release_wakelock(UA_WAKELOCK); + } + } + } +#endif + } + + //vTaskDelete(NULL); +} + +#define _________WIFI__RELATED________________________ + +int uartadapter_connect_wifi(rtw_network_info_t *p_wifi, uint32_t channel, uint8_t pscan_config) +{ + int retry = 3; + rtw_wifi_setting_t setting; + int ret; + while (1) { + if(wifi_set_pscan_chan((uint8_t *)&channel, &pscan_config, 1) < 0){ + ua_printf(UA_ERROR, "wifi set partial scan channel fail"); + ret = SC_TARGET_CHANNEL_SCAN_FAIL; + return ret; + } + + ret = wifi_connect((char*)p_wifi->ssid.val, + p_wifi->security_type, + (char*)p_wifi->password, + p_wifi->ssid.len, + p_wifi->password_len, + p_wifi->key_id, + NULL); + + if (ret == RTW_SUCCESS) { + ret = LwIP_DHCP(0, DHCP_START); + wifi_get_setting(WLAN0_NAME, &setting); + wifi_show_setting(WLAN0_NAME, &setting); + if (ret == DHCP_ADDRESS_ASSIGNED) + return SC_SUCCESS; + else + return SC_DHCP_FAIL; + } + + if (retry == 0) { + ret = SC_JOIN_BSS_FAIL; + break; + } + retry --; + } + + return ret; +} + + +static int uartadapter_load_wifi_config() +{ + flash_t flash; + struct wlan_fast_reconnect *data; + uint32_t channel; + uint8_t pscan_config; + char key_id; + rtw_network_info_t wifi = {0}; + int ret = SC_SUCCESS; + + + data = (struct wlan_fast_reconnect *)rtw_zmalloc(sizeof(struct wlan_fast_reconnect)); + device_mutex_lock(RT_DEV_LOCK_FLASH); + flash_stream_read(&flash, FAST_RECONNECT_DATA, sizeof(struct wlan_fast_reconnect), (uint8_t *)data); + device_mutex_unlock(RT_DEV_LOCK_FLASH); + if(*((uint32_t *) data) != ~0x0){ + memcpy(psk_essid, data->psk_essid, sizeof(data->psk_essid)); + memcpy(psk_passphrase, data->psk_passphrase, sizeof(data->psk_passphrase)); + memcpy(wpa_global_PSK, data->wpa_global_PSK, sizeof(data->wpa_global_PSK)); + memcpy(&channel, &(data->channel), 4); + sprintf(&key_id,"%d",(channel >> 28)); + channel &= 0xff; + 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); + + //set wifi connect + wifi.ssid.len = (int)strlen((char*)psk_essid); + memcpy(wifi.ssid.val, psk_essid, wifi.ssid.len); + wifi.key_id = key_id; + + //open mode + if(!strlen((char*)psk_passphrase)){ + wifi.security_type = RTW_SECURITY_OPEN; + } + //wep mode + else if( strlen((char*)psk_passphrase) == 5 || strlen((char*)psk_passphrase) == 13){ + wifi.security_type = RTW_SECURITY_WEP_PSK; + wifi.password = (unsigned char *)psk_passphrase; + wifi.password_len = (int)strlen((char const *)psk_passphrase); + } + //WPA/WPA2 + else{ + wifi.security_type = RTW_SECURITY_WPA2_AES_PSK; + wifi.password = (unsigned char *)psk_passphrase; + wifi.password_len = (int)strlen((char const *)psk_passphrase); + } + + ret = uartadapter_connect_wifi(&wifi, channel, pscan_config); + + //print_simple_config_result((enum ua_sc_result)ret); + + if(data) + rtw_mfree((u8*)data, sizeof(sizeof(struct wlan_fast_reconnect))); + + if(ret == SC_SUCCESS) + return RTW_SUCCESS; + else + return RTW_ERROR; + }else{ + ua_printf(UA_INFO, "No AP Profile read from FLASH, start simple configure"); + + if(data) + rtw_mfree((u8*)data, sizeof(sizeof(struct wlan_fast_reconnect))); + + return RTW_ERROR; + } +} + +#if CONFIG_INCLUDE_SIMPLE_CONFIG +int uartadapter_simple_config(char *pin_code){ + + enum sc_result ret = SC_ERROR; + wifi_enter_promisc_mode(); + if(init_test_data(pin_code) == 0){ + filter_add_enable(); + ret = simple_config_test(NULL); + //print_simple_config_result(ret); + remove_filter(); + if(ret == SC_SUCCESS) + return RTW_SUCCESS; + else + return RTW_ERROR; + }else{ + return RTW_ERROR; + } +} +#endif + +#define _________MDNS__RELATED________________________ +static void uartadapter_mdns_start(ua_socket_t *ua_socket, int is_restart) +{ + TXTRecordRef txtRecord; + unsigned char txt_buf[100] = {0}; // use fixed buffer for text record to prevent malloc/free + unsigned char txt_buf2[100] = {0}; // use fixed buffer for text record to prevent malloc/free + struct sockaddr_in server_addr; + int server_addr_len = sizeof(server_addr); + + struct netif * pnetif = &xnetif[0]; + + if(is_restart){ + ua_printf(UA_INFO, "Uart Adapter mDNS Restart"); + mDNSResponderDeinit(); + vTaskDelay(1000); + } + + ua_printf(UA_DEBUG, "Uart Adapter mDNS Init"); + + if(mDNSResponderInit() == 0) { + ua_printf(UA_INFO, "mDNS Register service"); + char hostname[32] = {0}; //AMEBA_UART-MODE + u32 prefix_len = strlen("AMEBA_"); + sprintf(hostname, "AMEBA_"); + sprintf(hostname+prefix_len, "%02x%02x%02x%02x%02x%02x", + pnetif->hwaddr[0], pnetif->hwaddr[1], pnetif->hwaddr[2], + pnetif->hwaddr[3], pnetif->hwaddr[4], pnetif->hwaddr[5]); + + sprintf(txt_buf2, "groupid:%d, tcpserver:%d", ua_socket->tcp.group_id, ua_socket->tcp.server_port); + TXTRecordCreate(&txtRecord, sizeof(txt_buf), txt_buf); + TXTRecordSetValue(&txtRecord, "groupid", strlen(txt_buf2), txt_buf2); + + ua_socket->dnsServiceRef = mDNSRegisterService(hostname, "_uart_data._tcp", "local", 5001, &txtRecord); + if(ua_socket->dnsServiceRef == NULL) + ua_printf(UA_ERROR, "mdns data service register failed!"); + ua_socket->dnsServiceRef2 = mDNSRegisterService(hostname, "_uart_control._tcp", "local", 6001, &txtRecord); + if(ua_socket->dnsServiceRef2 == NULL) + ua_printf(UA_ERROR, "mdns control service register failed!"); + TXTRecordDeallocate(&txtRecord); + + }else{ + ua_printf(UA_INFO, "mDNS Init Failed"); + } + + //vTaskDelete(NULL); +} + + + +#define _________INIT__RELATED________________________ +static void uartadapter_auto_reconnect(void* param) +{ + ua_socket_t *ua_socket = (ua_socket_t *)param; + uint32_t IPaddress, IPaddress2; + uint8_t iptab[4], iptab2[4]; + //int ret = 0; + + ua_reconnect_started = 1; + +#if CONFIG_AUTO_RECONNECT + wifi_set_autoreconnect(0); +#endif + vTaskDelay(1000); + while(uartadapter_load_wifi_config() != RTW_SUCCESS){ + vTaskDelay(2000); + } +#if CONFIG_AUTO_RECONNECT + wifi_set_autoreconnect(1); +#endif + + ua_printf(UA_INFO, "uart adapter reconnect successful"); + //uartadapter_gpio_led_mode(ua_global_socket, UART_ADAPTER_LED_OFF); + + if(0 == memcmp(&ua_socket->ip, &xnetif[0].ip_addr, sizeof(ip_addr_t))){ + IPaddress = ua_socket->ip.addr; + iptab[0] = (uint8_t)(IPaddress >> 24); + iptab[1] = (uint8_t)(IPaddress >> 16); + iptab[2] = (uint8_t)(IPaddress >> 8); + iptab[3] = (uint8_t)(IPaddress); + ua_printf(UA_INFO, "reconnect IP address no change, %d.%d.%d.%d", iptab[3], iptab[2], iptab[1], iptab[0]); + }else{ + IPaddress = ua_socket->ip.addr; + iptab[0] = (uint8_t)(IPaddress >> 24); + iptab[1] = (uint8_t)(IPaddress >> 16); + iptab[2] = (uint8_t)(IPaddress >> 8); + iptab[3] = (uint8_t)(IPaddress); + IPaddress2 = xnetif[0].ip_addr.addr; + iptab2[0] = (uint8_t)(IPaddress2 >> 24); + iptab2[1] = (uint8_t)(IPaddress2 >> 16); + iptab2[2] = (uint8_t)(IPaddress2 >> 8); + iptab2[3] = (uint8_t)(IPaddress2); + ua_printf(UA_INFO, "reconnect IP address changed from %d.%d.%d.%d to %d.%d.%d.%d", iptab[3], iptab[2], iptab[1], iptab[0], iptab2[3], iptab2[2], iptab2[1], iptab2[0]); + memcpy(&ua_socket->ip, &xnetif[0].ip_addr, sizeof(ip_addr_t)); + ua_reconnect_ip_change = 1; + + ua_printf(UA_INFO,"IP changed, remove TCP information in FLASH!"); + ua_socket->tcp.group_id = 0; + ua_socket->tcp.client_port = 0; + ua_socket->tcp.server_port = 0; + memset(ua_socket->tcp.client_ip, 0, 16); + + uartadapter_mdns_start(ua_socket, 1); + } + + + ua_reconnect_started = 0; + vTaskDelete(NULL); +} + +void uartadapter_auto_connect(void *param) +{ + int ret = 0; + ua_socket_t *ua_socket = (ua_socket_t *)param; + + UA_SOCKET_CHECK(ua_socket); + + if(wifi_is_ready_to_transceive(RTW_STA_INTERFACE) == RTW_SUCCESS) { + ua_printf(UA_INFO, "wifi connect successfully!"); + }else{ +#if CONFIG_AUTO_RECONNECT + wifi_set_autoreconnect(0); +#endif +RETRY: + vTaskDelay(2000); + ret = uartadapter_load_wifi_config(); + if(ret != RTW_SUCCESS){ + vTaskDelay(2000); +#if CONFIG_INCLUDE_SIMPLE_CONFIG + ret = uartadapter_simple_config(NULL); + if(ret != RTW_SUCCESS){ + ua_printf(UA_INFO, "Simple configure connect failed, try again!"); + goto RETRY; + } +#endif + } +#if CONFIG_AUTO_RECONNECT + wifi_set_autoreconnect(1); +#endif + } + + ua_wifi_connected = 1; + //uartadapter_gpio_led_mode(ua_global_socket, UART_ADAPTER_LED_OFF); + + memcpy(&ua_socket->ip, &xnetif[0].ip_addr, sizeof(ip_addr_t)); + + if(!sys_thread_new("tcp data server", uartadapter_tcp_chat_server_thread, (void *)ua_socket, 256, UA_UART_THREAD_PRIORITY)) + ua_printf(UA_ERROR, "%s sys_thread_new data server failed\n", __FUNCTION__); + + vTaskDelay(50); + if(!sys_thread_new("tcp control server", uartadapter_tcp_control_server_thread, (void *)ua_socket, 256, UA_UART_THREAD_PRIORITY)) + ua_printf(UA_ERROR, "%s sys_thread_new control server failed\n", __FUNCTION__); + + vTaskDelay(50); + + if(!sys_thread_new("tcp select", uartadapter_tcp_select_thread, (void *)ua_socket, 768, UA_UART_THREAD_PRIORITY)) + ua_printf(UA_ERROR, "%s sys_thread_new tcp select failed\n", __FUNCTION__); + + vTaskDelay(50); + + uartadapter_control_read_tcp_info_and_connect(ua_socket); + + vTaskDelay(50); + + uartadapter_mdns_start(ua_socket, 0); + + vTaskDelay(50); + + ua_printf(UA_INFO, "[MEM] After auao connect, available heap %d", xPortGetFreeHeapSize()); + + /* Kill init thread after all init tasks done */ + vTaskDelete(NULL); +} + +void uartadapter_exception_thread(void *param) +{ + int ret = 0; + unsigned int tick_start; + unsigned int tick_current; + int pin_high = 0; + int address = FAST_RECONNECT_DATA; + + ua_socket_t *ua_socket = (ua_socket_t *)param; + + while(RtlDownSema(&ua_exception_sema) == pdTRUE){ + if(ua_gpio_irq_happen){ + pin_high = 0; + tick_start = xTaskGetTickCount(); + tick_current = xTaskGetTickCount(); + while(tick_current - tick_start < 3000){ + if (gpio_read(&ua_socket->gpio.gpio_btn)){ + pin_high = 1; + break; + }else{ + tick_current = xTaskGetTickCount(); + } + vTaskDelay(10); + } + + ua_gpio_irq_happen = 0; + if(!pin_high){ + ret = uartadapter_flasherase(address, sizeof(rtw_wifi_config_t)); + if(ret < 0){ + ua_printf(UA_ERROR, "flash erase error!"); + } + + ret = uartadapter_flasherase(UA_FAST_RECONNECT_TCP_DATA, sizeof(ua_tcp_socket_t)); + if(ret < 0){ + ua_printf(UA_ERROR, "flash erase error!"); + } + + uartadapter_systemreload(); + } + } + } + + vTaskDelete(NULL); +} + +ua_socket_t* uartadapter_socket_init() +{ + ua_socket_t* ua_socket = NULL; + //int ret = 0; + + ua_socket = pvPortMalloc(sizeof(ua_socket_t)); + + if(NULL == ua_socket){ + ua_printf(UA_ERROR, "Allocate uart adapter socket failed."); + goto Exit2; + } + + ua_socket->uart.rcv_ch = 0; + ua_socket->uart.overlap = 0; + ua_socket->uart.recv_bytes = 0; + ua_socket->uart.pread = 0; + ua_socket->uart.pwrite = 0; + ua_socket->uart.tick_last_update = 0; + ua_socket->uart.tick_current = 0; + ua_socket->uart.rx_cnt = 0; + ua_socket->uart.miss_cnt = 0; + ua_socket->uart.tx_busy = 0; + RtlInitSema(&ua_socket->uart.action_sema, 0); + RtlInitSema(&ua_socket->uart.tcp_tx_rx_sema, 1); + RtlInitSema(&ua_socket->uart.dma_tx, 1); + + ua_socket->tcp.chat_socket= -1; + ua_socket->tcp.control_socket= -1; + ua_socket->tcp.chat_server_listen_socket= -1; + ua_socket->tcp.control_server_listen_socket= -1; + + ua_socket->tcp.transmit_recv_socket = -1; + ua_socket->tcp.transmit_send_socket = -1; + ua_socket->tcp.transmit_server_listen_socket = -1; + + ua_socket->tcp.group_id = 0; + ua_socket->tcp.server_port = 0; + ua_socket->tcp.client_port = 0; + memset(ua_socket->tcp.client_ip, 0, 16); + + ua_socket->tcp.send_flag = 0; + ua_socket->tcp.recv_flag = 0; + ua_socket->tcp.rx_cnt = 0; + ua_socket->tcp.tx_cnt = 0; + + ua_socket->uart.uart_ps = 0; + ua_socket->uart.uart_ps_cnt = 0; + ua_socket->tcp.tcp_ps = 0; + ua_socket->tcp.tcp_ps_cnt = 0; + + ua_socket->dnsServiceRef = NULL; + ua_socket->dnsServiceRef2 = NULL; + + return ua_socket; + +Exit2: + return NULL; + +} + +void uartadapter_disconnect_handler(char *buf, int buf_len, int flags, void *userdata) +{ + if(!ua_wifi_connected || ua_reconnect_started) + return; + + ua_printf(UA_DEBUG, "start uart adapter reconnect thread\r\n"); + //uartadapter_gpio_led_mode(ua_global_socket, UART_ADAPTER_LED_FAST_TWINKLE); + + if(xTaskCreate(uartadapter_auto_reconnect, ((const char*)"reconnect"), 512, (void *)ua_global_socket, UA_UART_THREAD_PRIORITY, NULL) != pdPASS) + ua_printf(UA_ERROR, "%s xTaskCreate(uart_rx) failed", __FUNCTION__); + +} + +int uartadapter_init() +{ + int ret = 0; + + RtlInitSema(&ua_print_sema, 1); + + ua_printf(UA_INFO, "==============>%s()\n", __func__); + + ua_global_socket = uartadapter_socket_init(); + if(ua_global_socket == NULL){ + ua_printf(UA_ERROR, "ua_socket init failed"); + ret = -1; + goto Exit; + } + +#if !UA_PS_ENABLE + acquire_wakelock(UA_WAKELOCK); +#endif + + RtlInitSema(&ua_exception_sema, 0); + + uartadapter_uart_init(ua_global_socket); + + uartadapter_gpio_init(ua_global_socket); + //uartadapter_gpio_led_mode(ua_global_socket, UART_ADAPTER_LED_FAST_TWINKLE); + + wifi_reg_event_handler(WIFI_EVENT_DISCONNECT, uartadapter_disconnect_handler, NULL); + + if(xTaskCreate(uartadapter_uart_rx_thread, ((const char*)"uart_rx"), 256, (void *)ua_global_socket, UA_UART_THREAD_PRIORITY, NULL) != pdPASS) + ua_printf(UA_ERROR, "%s xTaskCreate(uart_rx) failed", __FUNCTION__); + + vTaskDelay(50); + + if(xTaskCreate(uartadapter_auto_connect, ((const char*)"auto connnect"), 1024, (void *)ua_global_socket, UA_UART_THREAD_PRIORITY, NULL) != pdPASS) + ua_printf(UA_ERROR, "%s xTaskCreate(auao connnect) failed", __FUNCTION__); + + vTaskDelay(50); + + if(xTaskCreate(uartadapter_exception_thread, ((const char*)"uart main"), 128, (void *)ua_global_socket, UA_UART_THREAD_PRIORITY, NULL) != pdPASS) + ua_printf(UA_ERROR, "%s xTaskCreate(auao connnect) failed", __FUNCTION__); + + return 0; +Exit: + ua_printf(UA_ERROR, "%s(): Initialization failed!", __func__); + return ret; +} + +void example_uart_adapter_init() +{ + // Call back from wlan driver after wlan init done + p_wlan_uart_adapter_callback = uartadapter_init; +} + +#define _________CMD__RELATED________________________ +void uartadapter_print_irq_rx_count(ua_socket_t *ua_socket) +{ + UA_SOCKET_CHECK(ua_socket); + + ua_printf(UA_INFO, "ua_tick_last_update: %d!\n", ua_socket->uart.tick_last_update); + ua_printf(UA_INFO, "ua_tick_current: %d!\n", ua_socket->uart.tick_current); + ua_printf(UA_INFO, "ua current tick: %d!\n", xTaskGetTickCount()); + ua_printf(UA_INFO, "ua_pwrite: %d!\n", ua_socket->uart.pwrite); + ua_printf(UA_INFO, "ua_pread: %d!\n", ua_socket->uart.pread); + ua_printf(UA_INFO, "ua_overlap: %d!\n", ua_socket->uart.overlap); + ua_printf(UA_INFO, "ua_rcv_ch: %d!\n", ua_socket->uart.rcv_ch); + ua_printf(UA_INFO, "ua_uart_recv_bytes: %d!\n", ua_socket->uart.recv_bytes); + ua_printf(UA_INFO, "irq_rx_cnt: %d!\n", ua_socket->uart.rx_cnt); + ua_printf(UA_INFO, "irq_miss_cnt: %d!\n", ua_socket->uart.miss_cnt); + ua_printf(UA_INFO, "tcp_tx_cnt: %d!\n", ua_socket->tcp.tx_cnt); + ua_printf(UA_INFO, "tcp_rx_cnt: %d!\n", ua_socket->tcp.rx_cnt); + ua_printf(UA_INFO, "tcp_send_flag: %d!\n", ua_socket->tcp.send_flag); + ua_printf(UA_INFO, "tcp_recv_flag: %d!\n", ua_socket->tcp.recv_flag); + ua_printf(UA_INFO, "tcp_chat_socket: %d!\n", ua_socket->tcp.chat_socket); + ua_printf(UA_INFO, "tcp_control_socket: %d!\n", ua_socket->tcp.control_socket); + ua_printf(UA_INFO, "tcp_transmit_recv_socket: %d!\n", ua_socket->tcp.transmit_recv_socket); + ua_printf(UA_INFO, "tcp_transmit_send_socket: %d!\n", ua_socket->tcp.transmit_send_socket); + ua_printf(UA_INFO, "tcp_chat_server_listen_socket: %d!\n", ua_socket->tcp.chat_server_listen_socket); + ua_printf(UA_INFO, "tcp_control_server_listen_socket: %d!\n", ua_socket->tcp.control_server_listen_socket); + ua_printf(UA_INFO, "tcp_transmit_server_listen_socket: %d!\n", ua_socket->tcp.transmit_server_listen_socket); + +} + +void uartadapter_reset_irq_rx_count(ua_socket_t *ua_socket) +{ + UA_SOCKET_CHECK(ua_socket); + + ua_socket->uart.rx_cnt = 0; + ua_socket->uart.miss_cnt = 0; + ua_socket->tcp.rx_cnt = 0; + ua_socket->tcp.tx_cnt = 0; +} + +void uartadapter_set_debug_print(bool enable) +{ + ua_debug_print_en = enable; +} + +void cmd_uart_adapter(int argc, char **argv) +{ + if(argc < 2) { + printf("\n\r inpua error\n"); + return; + } + + if(strcmp(argv[1], "help") == 0){ + printf("\r\nUART THROUGH COMMAND LIST:"); + printf("\r\n=============================="); + printf("\r\n\tuart_baud"); + printf("\r\n"); + }else if(strcmp(argv[1], "irq_rx_get") == 0){ + uartadapter_print_irq_rx_count(ua_global_socket); + }else if(strcmp(argv[1], "debug_print_en") == 0){ + uartadapter_set_debug_print(TRUE); + }else if(strcmp(argv[1], "debug_print_dis") == 0){ + uartadapter_set_debug_print(FALSE); + }else if(strcmp(argv[1], "irq_rx_reset") == 0){ + uartadapter_reset_irq_rx_count(ua_global_socket); + }else if(strcmp(argv[1], "tcp") == 0){ + unsigned int port; + if(strcmp(argv[2], "-c") == 0 || strcmp(argv[2], "c") == 0){ + strncpy(ua_tcp_server_ip, argv[3], (strlen(argv[3])>16)?16:strlen(argv[3])); + port = atoi(argv[4]); + if(xTaskCreate(uartadapter_tcp_transmit_client_thread, ((const char*)"tclient"), 256, (void *)port, UA_UART_THREAD_PRIORITY, NULL) != pdPASS) + ua_printf(UA_ERROR, "%s xTaskCreate(tcp client) failed", __FUNCTION__); + }else if(strcmp(argv[2], "-s") == 0 || strcmp(argv[2], "s") == 0){ + port = atoi(argv[3]); + if(xTaskCreate(uartadapter_tcp_transmit_server_thread, ((const char*)"tserver"), 256, (void *)port, UA_UART_THREAD_PRIORITY, NULL) != pdPASS) + ua_printf(UA_ERROR, "%s xTaskCreate(tcp server) failed", __FUNCTION__); + } + }else if(strcmp(argv[1], "uart_baud") == 0){ + uartadapter_uart_baud(ua_global_socket, atoi(argv[2])); + }else if(strcmp(argv[1], "uart_para") == 0){ + uartadapter_uart_para(ua_global_socket, atoi(argv[2]), atoi(argv[3]), atoi(argv[4])); + }else if(strcmp(argv[1], "led") == 0){ + //uartadapter_gpio_led_mode(ua_global_socket, atoi(argv[2])); + }else{ + printf("\n\rCan not find the input commond!"); + } +} + diff --git a/component/common/application/uart_adapter/uart_adapter.h b/component/common/application/uart_adapter/uart_adapter.h new file mode 100644 index 0000000..e1edab5 --- /dev/null +++ b/component/common/application/uart_adapter/uart_adapter.h @@ -0,0 +1,264 @@ +#include "osdep_api.h" +#include "serial_api.h" +#include +#include "freertos_pmu.h" +#include +/****************************************************** + * Macros + ******************************************************/ +#define UA_ERROR 0 +#define UA_WARNING 1 +#define UA_INFO 2 +#define UA_DEBUG 3 +#define UA_NONE 0xFF +#define UA_DEBUG_LEVEL UA_INFO + +#define UA_UART_THREAD_PRIORITY 5 +#define UA_UART_THREAD_STACKSIZE 512 + +#define UA_TCP_SERVER_FD_NUM 1 +#define UA_TCP_CLIENT_FD_NUM 1 + +#define UA_UART_RECV_BUFFER_LEN 8196 +#define UA_UART_FRAME_LEN 1400 +#define UA_UART_MAX_DELAY_TIME 100 + +#define UA_CHAT_SOCKET_PORT 5001 +#define UA_CONTROL_SOCKET_PORT 6001 + +#define UA_UART_TX_PIN PA_7 +#define UA_UART_RX_PIN PA_6 + +#define UA_GPIO_LED_PIN PC_5 +#define UA_GPIO_IRQ_PIN PC_4 + +#define UA_CONTROL_PREFIX "AMEBA_UART" + +#define UA_PS_ENABLE 0 +#define UA_GPIO_WAKEUP_PIN PC_3 +#define UA_WAKELOCK WAKELOCK_USER_BASE + +#define UA_FAST_RECONNECT_TCP_DATA (0x80000 - 0x2000) + + +#if (UA_DEBUG_LEVEL== UA_NONE) +#define ua_printf(level, fmt, arg...) +#else +#define ua_printf(level, fmt, arg...) \ +do {\ + if (level <= UA_DEBUG_LEVEL) {\ + if (level <= UA_ERROR) {\ + RtlDownSema(&ua_print_sema);\ + printf("\r\nERROR: " fmt, ##arg);\ + RtlUpSema(&ua_print_sema);\ + } \ + else {\ + RtlDownSema(&ua_print_sema);\ + printf("\r\n"fmt, ##arg);\ + RtlUpSema(&ua_print_sema);\ + } \ + }\ +}while(0) +#endif + +#define UA_PRINT_DATA(_HexData, _HexDataLen) \ + if(UA_DEBUG_LEVEL == UA_DEBUG) \ + { \ + int __i; \ + u8 *ptr = (u8 *)_HexData; \ + printf("--------Len=%d\n\r", _HexDataLen); \ + for( __i=0; __i<(int)_HexDataLen; __i++ ) \ + { \ + printf("%02X%s", ptr[__i], (((__i + 1) % 4) == 0)?" ":" "); \ + if (((__i + 1) % 16) == 0) printf("\n\r"); \ + } \ + printf("\n\r"); \ + } + +#define UA_SOCKET_CHECK(_ua_socket) \ + if(_ua_socket == NULL) \ + { \ + printf("ERROR: ua_socket = NULL\n\r"); \ + return; \ + } + +#define UA_SOCKET_CHECK_2(_ua_socket) \ + if(_ua_socket == NULL) \ + { \ + printf("ERROR: ua_socket = NULL\n\r"); \ + return -1; \ + } + +/****************************************************** + * Constants + ******************************************************/ +typedef enum +{ + UART_ADAPTER_LED_ON = 0, + UART_ADAPTER_LED_OFF = 1, + UART_ADAPTER_LED_FAST_TWINKLE = 2, + UART_ADAPTER_LED_SLOW_TWINKLE = 3, +}ua_led_mode_t; + +typedef enum +{ + UART_CTRL_MODE_SET_REQ = 0, + UART_CTRL_MODE_SET_RSP = 1, + UART_CTRL_MODE_GET_REQ = 2, + UART_CTRL_MODE_GET_RSP = 3, +}ua_ctrl_mode_t; + +typedef enum +{ + UART_CTRL_TYPE_BAUD_RATE = 0x01, + UART_CTRL_TYPE_WORD_LEN = 0x02, + UART_CTRL_TYPE_PARITY = 0x04, + UART_CTRL_TYPE_STOP_BIT = 0x08, + UART_CTRL_TYPE_TCP_SERVER_CREATE = 0x10, + UART_CTRL_TYPE_TCP_SERVER_DELETE = 0x20, + UART_CTRL_TYPE_TCP_CLIENT_CONNECT = 0x40, + UART_CTRL_TYPE_TCP_CLIENT_DISCONNECT = 0x80, + UART_CTRL_TYPE_TCP_GROUP_ID = 0x100, +}ua_ctrl_type_t; + +enum sc_result { + SC_ERROR = -1, /* default error code*/ + SC_NO_CONTROLLER_FOUND = 1, /* cannot get sta(controller) in the air which starts a simple config session */ + SC_CONTROLLER_INFO_PARSE_FAIL, /* cannot parse the sta's info */ + SC_TARGET_CHANNEL_SCAN_FAIL, /* cannot scan the target channel */ + SC_JOIN_BSS_FAIL, /* fail to connect to target ap */ + SC_DHCP_FAIL, /* fail to get ip address from target ap */ + /* fail to create udp socket to send info to controller. note that client isolation + must be turned off in ap. we cannot know if ap has configured this */ + SC_UDP_SOCKET_CREATE_FAIL, + SC_SUCCESS, /* default success code */ +}; + +/****************************************************** + * Structures + ******************************************************/ + typedef struct _ua_uart_param_t +{ + u8 WordLen; + u8 Parity; + u8 StopBit; + u8 FlowControl; + int BaudRate; +}ua_uart_param_t; + +typedef struct _ua_uart_socket_t +{ + int fd; + char rcv_ch; + volatile char overlap; + int recv_bytes; + volatile int pread; + volatile int pwrite; + + volatile unsigned int tick_last_update; + unsigned int tick_current; + + volatile int tx_busy; + + volatile int uart_ps; + volatile int uart_ps_cnt; + + char recv_buf[UA_UART_RECV_BUFFER_LEN]; + + long rx_cnt; + long miss_cnt; + + serial_t uart_sobj; + ua_uart_param_t uart_param; + + _Sema action_sema; + _Sema tcp_tx_rx_sema; + _Sema dma_tx; +}ua_uart_socket_t; + +typedef struct _ua_tcp_socket_t +{ + int chat_socket; + int control_socket; + int chat_server_listen_socket; + int control_server_listen_socket; + + int transmit_recv_socket; + int transmit_send_socket; + int transmit_server_listen_socket; + + int group_id; + u32 server_port; + u32 client_port; + char client_ip[16]; + + + int send_flag; + int recv_flag; + long rx_cnt; + long tx_cnt; + + volatile int tcp_ps; + volatile int tcp_ps_cnt; +}ua_tcp_socket_t; + +typedef struct _ua_gpio_t +{ + gpio_t gpio_led; + gpio_t gpio_btn; + gpio_irq_t gpio_btn_irq; + gtimer_t gpio_timer; +}ua_gpio_t; + +typedef struct _ua_socket_t +{ + ua_uart_socket_t uart; + ua_tcp_socket_t tcp; + ua_gpio_t gpio; + ip_addr_t ip; + DNSServiceRef dnsServiceRef; + DNSServiceRef dnsServiceRef2; +}ua_socket_t; + +typedef struct _ua_mbox_buffer +{ + char data[UA_UART_FRAME_LEN]; + int data_len; +}ua_mbox_buffer_t; + +//Save Uart Settings when get uart information +typedef struct _ua_uart_get_str +{ + int BaudRate; //The baud rate + char number; //The number of data bits + char parity; //The parity(0: none, 1:odd, 2:evn, default:0) + char StopBits; //The number of stop bits + char FlowControl; //support flow control is 1 +}ua_uart_get_str; + +//Uart Setting information +typedef struct _ua_uart_set_str +{ + char UartName[8]; // the name of uart + int BaudRate; //The baud rate + char number; //The number of data bits + char parity; //The parity(default NONE) + char StopBits; //The number of stop bits + char FlowControl; //support flow control is 1 +}ua_uart_set_str; + + +int uartadapter_init(); +void uartadapter_tcp_send_data(ua_socket_t *ua_socket, char *buffer, int size); +void uartadapter_tcp_send_control(ua_socket_t *ua_socket, char *buffer, int size); +void uartadapter_tcp_transmit_server_thread(void *param); +void uartadapter_tcp_transmit_client_thread(void *param); +int uartadapter_tcpclient(ua_socket_t *ua_socket, const char *host_ip, unsigned short usPort); +void uartadapter_tcp_transmit_client_forever_thread(void *param); + + +void example_uart_adapter_init(); +void cmd_uart_adapter(int argc, char **argv); + +void uartadapter_tcp_transmit_socket_handler(ua_socket_t *ua_socket, char *tcp_rxbuf); + diff --git a/component/common/application/wigadget/cloud_link.c b/component/common/application/wigadget/cloud_link.c new file mode 100644 index 0000000..0279951 --- /dev/null +++ b/component/common/application/wigadget/cloud_link.c @@ -0,0 +1,82 @@ +#include "FreeRTOS.h" +#include "task.h" +#include "wifi_conf.h" +#include "wifi_ind.h" +#include "google_nest.h" +#include "flash_api.h" +#include "wigadget.h" +#include +#include "shtc1.h" + +#define CLOUD_PORT 443 +extern struct netif xnetif[NET_IF_NUM]; + +void cloud_link_task(void *param){ + googlenest_context googlenest; + unsigned char URI[64]; + unsigned char data[97] = {0}; + unsigned char host_addr[64] = {0}; + flash_t cloud_flash; + u8 *mac = (u8 *)LwIP_GetMAC(&xnetif[0]); + char i[16], j[16]; + float temperature = 1.123f; + float humidity = 2.456f; + int ret = 0; + + vTaskDelay(2000); + + + sprintf(URI, "ht_sensor/%02x%02x%02x%02x%02x%02x.json", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + memset(host_addr, 0, sizeof(host_addr)); + if(flash_stream_read(&cloud_flash, FLASH_IOT_DATA, 97, (uint8_t *) data) == 1){ + + memset(host_addr, 0 , 64); + memcpy(host_addr, data+33, 64); + while(1) { + printf("\r\n\r\n\r\n\r\n\r\n\r\n=====>START CLOUD LINKING\r\n\r\n"); + memset(i, 0, 16); + memset(j, 0, 16); +#if PSEUDO_DATA + sprintf(i,"%.2f", temperature++); + sprintf(j, "%.2f", humidity++); + if(temperature > 60) + temperature = 1.123f; + if(humidity > 98) + humidity = 2.456f; +#else + ret = SHTC_GetTempAndHumi(&temperature, &humidity); + sprintf(i,"%.2f", temperature); + sprintf(j, "%.2f", humidity); +#endif + if(ret < 0) + printf("\r\n\r\n<-----LOCAL LINK FAILED!!(get infor failed)\r\n\r\n"); + else{ + gen_json_data(i,j, data); + printf("\r\nCLOUD-LINK--Sending data : \r\n%s\r\n", data); + memset(&googlenest, 0, sizeof(googlenest_context)); + if(gn_connect(&googlenest, host_addr, CLOUD_PORT) == 0) { + if(gn_put(&googlenest, URI, data) != 0) + printf("\r\n\r\nPUT data failed!\r\n\r\n"); + gn_close(&googlenest); + printf("\r\n\r\n<=====CLOUD LINK OK!!\r\n\r\n"); + } + else{ + printf("\r\n\r\n<=====CLOUD LINK FAILED!!(google nest connecting)\r\n\r\n"); + } + free(data); + vTaskDelay(10000); + } + } + + } + else + printf("\r\n\r\n<=====CLOUD LINK FAILED!!(flash reading)\r\n\r\n"); + +} + +void start_cloud_link(void) +{ +if(xTaskCreate(cloud_link_task, ((const char*)"cloud_link_task"), 3584, NULL, tskIDLE_PRIORITY + 4, NULL) != pdPASS) + printf("\n\r%s xTaskCreate failed", __FUNCTION__); +} \ No newline at end of file diff --git a/component/common/application/wigadget/cloud_link.h b/component/common/application/wigadget/cloud_link.h new file mode 100644 index 0000000..a0d3710 --- /dev/null +++ b/component/common/application/wigadget/cloud_link.h @@ -0,0 +1,11 @@ +#ifndef CLOUD_LINK_H +#define CLOUD_LINK_THREAD_H + +#include "wigadget.h" + +void start_cloud_link(void); +void cloud_link_task(void *param); + + +#endif + diff --git a/component/common/application/wigadget/shtc1.c b/component/common/application/wigadget/shtc1.c new file mode 100644 index 0000000..2d590db --- /dev/null +++ b/component/common/application/wigadget/shtc1.c @@ -0,0 +1,185 @@ +#include "device.h" +#include "PinNames.h" +#include "basic_types.h" +#include "diag.h" +#include "osdep_api.h" +#include "i2c_api.h" +#include "pinmap.h" +#include "shtc1.h" + +#define MBED_I2C_MTR_SDA PB_3 +#define MBED_I2C_MTR_SCL PB_2 + +#define MBED_I2C_SLAVE_ADDR0 0x70 +#define POLYNOMIAL 0x131 // P(x) = x^8 + x^5 + x^4 + 1 = 100110001 + +#define MBED_I2C_BUS_CLK 100000 //hz +#define I2C_DATA_MAX_LENGTH 16 + +static uint8_t i2cdata_write[I2C_DATA_MAX_LENGTH]; +static uint8_t i2cdata_read[I2C_DATA_MAX_LENGTH]; +static int i2cdata_read_pos; + +static i2c_t i2cmaster; + +// Sensor Commands +#define READ_ID 0xEFC8 // command: read ID register +#define SOFT_RESET 0x805D // soft resetSample Code for SHTC1 +#define MEAS_T_RH_POLLING 0x7866 // meas. read T first, clock stretching disabled +#define MEAS_T_RH_CLOCKSTR 0x7CA2 // meas. read T first, clock stretching enabled +#define MEAS_RH_T_POLLING 0x58E0 // meas. read RH first, clock stretching disabled +#define MEAS_RH_T_CLOCKSTR 0x5C24 // meas. read RH first, clock stretching enabled + + +static int SHTC1_GetID(uint16_t *id); +static void SHTC1_WriteCommand(uint16_t cmd); +static int SHTC1_Read2BytesAndCrc(uint16_t *data); +static int SHTC1_CheckCrc(uint8_t data[], uint8_t nbrOfBytes, uint8_t checksum); +static float SHTC1_CalcTemperature(uint16_t rawValue); +static float SHTC1_CalcHumidity(uint16_t rawValue); + + +int SHTC_Init(uint16_t *pID) +{ + int error = NO_ERROR; + + DiagPrintf("SHTC1_Init \r\n"); + + i2c_init((i2c_t*)&i2cmaster, MBED_I2C_MTR_SDA ,MBED_I2C_MTR_SCL); + i2c_frequency((i2c_t*)&i2cmaster,MBED_I2C_BUS_CLK); + + if (pID == NULL ) + return NULL_ERROR; + error = SHTC1_GetID(pID); + + return error; +} + +static int SHTC1_GetID(uint16_t *id) +{ + int error = NO_ERROR; + uint8_t bytes[2]; + uint8_t checksum; + + SHTC1_WriteCommand(READ_ID); + + i2c_read((i2c_t*)&i2cmaster, MBED_I2C_SLAVE_ADDR0, (char*)&i2cdata_read[0], 3, 1); + i2cdata_read_pos = 0; + error = SHTC1_Read2BytesAndCrc(id); + + return error; +} + +static int SHTC1_Read2BytesAndCrc(uint16_t *data) +{ + int error; + int readed; + uint8_t bytes[2]; + uint8_t checksum; + + bytes[0] = i2cdata_read[i2cdata_read_pos++]; + bytes[1] = i2cdata_read[i2cdata_read_pos++]; + checksum = i2cdata_read[i2cdata_read_pos++]; + + error = SHTC1_CheckCrc(bytes, 2, checksum); + *data = (bytes[0] << 8) | bytes[1]; + + return error; +} + +static int SHTC1_CheckCrc(uint8_t data[], uint8_t nbrOfBytes, uint8_t checksum) +{ + uint8_t bit; // bit mask + uint8_t crc = 0xFF; // calculated checksum + uint8_t byteCtr; // byte counter + + for(byteCtr = 0; byteCtr < nbrOfBytes; byteCtr++){ + crc ^= (data[byteCtr]); + for(bit = 8; bit > 0; --bit){ + if(crc & 0x80) + crc = (crc << 1) ^ POLYNOMIAL; + else + crc = (crc << 1); + } + } + + if(crc != checksum) + return CHECKSUM_ERROR; + else + return NO_ERROR; +} + +static void SHTC1_WriteCommand(uint16_t cmd) +{ + int writebytes; + + i2cdata_write[0] = (uint8_t)(cmd >>8); + i2cdata_write[1] = (uint8_t)(cmd&0xFF); + i2c_write((i2c_t*)&i2cmaster, MBED_I2C_SLAVE_ADDR0, &i2cdata_write[0], 2, 1); +} + +static float SHTC1_CalcTemperature(uint16_t rawValue) +{ + return 175.0 * (float)rawValue / 65536.0 - 45.0; +} + +static float SHTC1_CalcHumidity(uint16_t rawValue) +{ + return 100.0 * (float)rawValue / 65536.0; +} + +int SHTC_GetTempAndHumi(float *temp, float *humi) +{ + int error; + uint16_t rawValueTemp; + uint16_t rawValueHumi; + + SHTC1_WriteCommand(MEAS_T_RH_CLOCKSTR); + + i2c_read((i2c_t*)&i2cmaster, MBED_I2C_SLAVE_ADDR0, (char*)&i2cdata_read[0], 6, 1); + i2cdata_read_pos = 0; + error = NO_ERROR; + error |= SHTC1_Read2BytesAndCrc(&rawValueTemp); + error |= SHTC1_Read2BytesAndCrc(&rawValueHumi); + + if ( error == NO_ERROR ) { + *temp = SHTC1_CalcTemperature(rawValueTemp); + *humi = SHTC1_CalcHumidity(rawValueHumi); + } + + return error; +} + +static void example_shtc1_thread(void *param) +{ + int error; + uint16_t shtc1_id; + float temperature = 1.123f; + float humidity = 2.456f; + + DBG_8195A("sleep 10 sec. to wait for UART console\n"); + RtlMsleepOS(10000); + DBG_8195A("start i2c example - SHTC1\n"); + + error = SHTC_Init(&shtc1_id); + if ( error == NO_ERROR ) + DiagPrintf("SHTC1 init ok, id=0x%x\r\n", shtc1_id); + else { + DiagPrintf("SHTC1 init FAILED! \r\n"); + for(;;); + } + + while(1){ + error = SHTC_GetTempAndHumi(&temperature, &humidity); + rtl_printf("temp=%f, humidity=%f, error=%d\n", temperature, humidity, error); + RtlMsleepOS(1000); + } +} + +void example_shtc1(void) +{ + if(xTaskCreate(example_shtc1_thread, ((const char*)"example_shtc1_thread"), 512, NULL, tskIDLE_PRIORITY + 1, NULL) != pdPASS) + printf("\n\r%s xTaskCreate(init_thread) failed", __FUNCTION__); +} + + diff --git a/component/common/application/wigadget/shtc1.h b/component/common/application/wigadget/shtc1.h new file mode 100644 index 0000000..5974237 --- /dev/null +++ b/component/common/application/wigadget/shtc1.h @@ -0,0 +1,13 @@ +#ifndef SHTC1_H +#define SHTC1_H + +#define NO_ERROR 0x00 +#define ACK_ERROR 0x01 +#define CHECKSUM_ERROR 0x02 +#define NULL_ERROR 0x03 + +int SHTC_GetTempAndHumi(float *temp, float *humi); +int SHTC_Init(uint16_t *pID); +void example_shtc1(void); + +#endif diff --git a/component/common/application/wigadget/wigadget.c b/component/common/application/wigadget/wigadget.c new file mode 100644 index 0000000..19fd909 --- /dev/null +++ b/component/common/application/wigadget/wigadget.c @@ -0,0 +1,727 @@ +#include "FreeRTOS.h" +#include "task.h" +#include "wifi_conf.h" +#include "wifi_ind.h" +#include "sockets.h" +#include +#include +#include +#include "flash_api.h" +#include +#include "rom_wac_curve25519-donna.h" +#include "gpio_api.h" +#include "gpio_irq_api.h" +#include "cJSON.h" +#include "cloud_link.h" +#include "wigadget.h" +#include "shtc1.h" + +#define PORT 6866 +#define MAX_BUFFER_SIZE 256 +#define ENC_SIZE 64 +#define CONTROL_TYPE 1 +#define GPIO_SOFTAP_RESET_PIN PC_4 + +flash_t iot_flash; +uint8_t aes_key[16]; +static unsigned char tx_buffer[MAX_BUFFER_SIZE]; +static unsigned char rx_buffer[MAX_BUFFER_SIZE]; + +extern struct netif xnetif[NET_IF_NUM]; + +#define DEBUG_IOT 1 + +#define IOT_LOG(level, fmt, ...) printf("\n\r[IOT %s] %s: " fmt "\n", level, __FUNCTION__, ##__VA_ARGS__) +#if DEBUG_IOT == 2 +#define IOT_DEBUG(fmt, ...) IOT_LOG("DEBUG", fmt, ##__VA_ARGS__) +#else +#define IOT_DEBUG(fmt, ...) +#endif +#if DEBUG_IOT +#define IOT_ERROR(fmt, ...) IOT_LOG("ERROR", fmt, ##__VA_ARGS__) +#else +#define IOT_ERROR(fmt, ...) +#endif + +void encrypt_data_aes(unsigned char *plaint_text, unsigned char *enc_data); +void decrypt_data_aes(unsigned char *enc_data, unsigned char *dec_data, int data_len); + + + +static unsigned int arc4random(void) +{ + unsigned int res = xTaskGetTickCount(); + static unsigned int seed = 0xDEADB00B; + + seed = ((seed & 0x007F00FF) << 7) ^ + ((seed & 0x0F80FF00) >> 8) ^ // be sure to stir those low bits + (res << 13) ^ (res >> 9); // using the clock too! + return seed; + +} + +static char *iot_itoa(int value) +{ + char *val_str; + int tmp = value, len = 1; + + while((tmp /= 10) > 0) + len ++; + + val_str = (char *) malloc(len + 1); + sprintf(val_str, "%d", value); + + return val_str; +} + + void gen_json_data(char *i, char *j, unsigned char *json_data) +{ + cJSON_Hooks memoryHook; + + memoryHook.malloc_fn = malloc; + memoryHook.free_fn = free; + cJSON_InitHooks(&memoryHook); + memset(json_data, 0, ENC_SIZE); + + + cJSON *IOTJSObject = NULL; + char *data; + + + if((IOTJSObject = cJSON_CreateObject()) != NULL) { + + cJSON_AddItemToObject(IOTJSObject, "TEM", cJSON_CreateString(i)); + cJSON_AddItemToObject(IOTJSObject, "HUM", cJSON_CreateString(j)); + + data = cJSON_Print(IOTJSObject); + memcpy(json_data, data, strlen(data)); + cJSON_Delete(IOTJSObject); + free(data); + } + +} + +void encrypt_data_aes(unsigned char *plaint_text, unsigned char *enc_data) +{ + unsigned char iv[16] = {0}; + unsigned char* iv_bak = "AAAAAAAAAAAAAAAA"; + aes_encrypt_ctx enc_ctx; + + memset(&enc_ctx, 0, sizeof(enc_ctx)); + memset(iv, 0, sizeof(iv)); + memcpy(iv, iv_bak, sizeof(iv)); + memset(enc_data, 0, sizeof(enc_data)); + + aes_init(); + aes_encrypt_key(aes_key, 16, &enc_ctx); + aes_cbc_encrypt(plaint_text, enc_data, ENC_SIZE, iv, &enc_ctx); +} + +void decrypt_data_aes(unsigned char *enc_data, unsigned char *dec_data, int data_len) +{ + unsigned char iv[16] = {0}; + unsigned char* iv_bak = "AAAAAAAAAAAAAAAA"; + aes_decrypt_ctx dec_ctx; + + memset(&dec_ctx, 0, sizeof(dec_ctx)); + memset(iv, 0, sizeof(iv)); + memcpy(iv, iv_bak, sizeof(iv)); + memset(dec_data, 0, sizeof(dec_data)); + + aes_init(); + aes_decrypt_key(aes_key, 16, &dec_ctx); + aes_cbc_decrypt(enc_data, dec_data, data_len, iv, &dec_ctx); + IOT_DEBUG("Decrypt data: %s\r\n",dec_data); +} + +void iotapp_platform_reset(void) +{ + HAL_WRITE32(SYSTEM_CTRL_BASE, 0x14, 0x00000021); + osDelay(100); + HAL_WRITE32(0xE000ED00, 0x0C, (0x5FA << 16) | + (HAL_READ32(0xE000ED00, 0x0C) & (7 << 8)) | + (1 << 2)); + while(1) osDelay(1000); +} + +void iotapp_reset_irq_handler(uint32_t id, gpio_irq_event event) +{ + printf("\n\r\n\r\n\r\n\r<<<<<>>>>>>\n\r\n\r\n\r\n\r"); + flash_erase_sector(&iot_flash, FLASH_IOT_DATA); + iotapp_platform_reset(); +} + +int local_link(unsigned char *tx_data) +{ + int sockfd, newsockfd; + socklen_t client; + struct sockaddr_in serv_addr, cli_addr; + uint8_t rx_data[ENC_SIZE]; + unsigned char enc_data[ENC_SIZE]; + unsigned char dec_data[ENC_SIZE]; + int ret = 0, opt = 1, k = 1, j; + char *result = NULL, *backup = NULL; + unsigned char *data = NULL; + char *delims = ", "; + + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) { + IOT_ERROR("ERROR opening socket"); + ret = -1; + goto exit2; + } + + if((setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof(opt))) < 0){ + IOT_ERROR("ERROR on setting socket option"); + ret = -1; + goto exit2; + } + + memset((char *)&serv_addr, 0, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = INADDR_ANY; + serv_addr.sin_port = htons(PORT); + + if (bind(sockfd, (struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0) { + IOT_ERROR("ERROR on binding"); + ret = -1; + goto exit2; + } + if(listen(sockfd , 20) < 0){ + IOT_ERROR("ERROR on listening"); + ret = -1; + goto exit2; + } + client = sizeof(cli_addr); + if((newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr,&client)) < 0){ + IOT_ERROR("ERROR on accept"); + ret = -1; + goto exit; + } + if ((ret = read(newsockfd,rx_buffer,sizeof(rx_buffer))) < 0){ + IOT_ERROR("ERROR reading from socket"); + ret = -1; + goto exit; + } + IOT_DEBUG("cmd received: %s, length: %d\r\n",rx_buffer, ret); + +//Changing received data to string + if (!strncmp(rx_buffer, "[", strlen("["))){ + data = rx_buffer + strlen("["); + for(j = 1; j < 5; j++){ + if (data[ret - j] == ']') + data[ret -j] = '\0'; + } + } + else + strcpy(data, rx_buffer); + memset(rx_data, 0, sizeof(rx_data)); + result = strtok_r(data, delims, &backup); + rx_data[0]=(uint8_t)atoi(result); + while((result = strtok_r(NULL, delims, &backup)) != NULL) + rx_data[k++]=(uint8_t)atoi(result); + memset(dec_data, 0, sizeof(dec_data)); + +//Decrpyt the received data + decrypt_data_aes(rx_data, dec_data, 16); + + if(strncmp(dec_data, "request", strlen("request")) == 0){ +//Encrypt the sending data + memset(enc_data, 0, strlen(enc_data)); + encrypt_data_aes(tx_data, enc_data); +//Changing encrpyt data to JAVA type string + for (j = 0; j < ENC_SIZE; j++){ + char *temp; + temp = iot_itoa(enc_data[j]); + if(j == 0) + strcpy(tx_buffer, "["); + strcat(tx_buffer,temp); + if (j == (ENC_SIZE - 1)) + strcat(tx_buffer,"]"); + else + strcat(tx_buffer,","); + free(temp); + temp = NULL; + } + IOT_DEBUG("Data reply to APP: %s\r\nLength of data: %d\r\n", tx_buffer, strlen(tx_buffer)); + + if ((ret = write(newsockfd,tx_buffer,strlen(tx_buffer))) < 0){ + IOT_ERROR("ERROR writing to socket"); + ret = -1; + goto exit; + } + else + IOT_DEBUG("Sending %d bytes data OK!\r\n", ret); + } + else if(strncmp(dec_data, "remove", strlen("remove")) == 0){ + printf("\n\r\n\r\n\r\n\r<<<<<>>>>>>\n\r\n\r\n\r\n\r"); + flash_erase_sector(&iot_flash, FLASH_IOT_DATA); + write(newsockfd,"Remove OK",strlen("Remove OK")); + close(newsockfd); + close(sockfd); + iotapp_platform_reset(); + } + else{ + IOT_ERROR("ERROR wrong KEY or wrong request!"); + write(newsockfd,"The KEY or the request is not correct!",strlen("The KEY or the request is not correct!")); + ret = -1; + goto exit; + } + +exit: + if(close(newsockfd) != 0) + goto exit; + +exit2: + if(close(sockfd) != 0) + goto exit2; + return ret; +} + +static void local_link_task(void *param) +{ + unsigned char data[ENC_SIZE] = {0}; + vTaskDelay(1000); + char i[16], j[16]; + float temperature = 1.123f; + float humidity = 2.456f; + int ret = 0; + + while(1){ + memset(i, 0, 16); + memset(j, 0, 16); +#if PSEUDO_DATA + sprintf(i,"%.2f", temperature++); + sprintf(j, "%.2f", humidity++); + if(temperature > 60) + temperature = 1.123f; + if(humidity > 98) + humidity = 2.456f; +#else + ret = SHTC_GetTempAndHumi(&temperature, &humidity); + sprintf(i,"%.2f", temperature); + sprintf(j, "%.2f", humidity); +#endif + if(ret < 0) + printf("\r\n\r\n<-----LOCAL LINK FAILED!!(get infor failed)\r\n\r\n"); + else{ + printf("\r\n\r\n----->START LOCAL LINKING\r\n\r\n"); + gen_json_data(i, j, data); + printf("Sending data : %s\r\n", data); + if (local_link(data) < 0) + printf("\r\n\r\n<-----LOCAL LINK FAILED!!\r\n\r\n"); + else + printf("\r\n\r\n<-----LOCAL LINK OK!!\r\n\r\n"); + vTaskDelay(1000); + } + } +} + +void start_local_link(void) +{ + if(xTaskCreate(local_link_task, ((const char*)"local_link_task"), 5376, NULL, tskIDLE_PRIORITY + 4, NULL) != pdPASS) + printf("\n\r%s xTaskCreate failed", __FUNCTION__); +} +int pair_device(unsigned char *tx_buffer, unsigned char *rx_buffer, int handshake) +{ + int sockfd, newsockfd; + socklen_t clilen; + struct sockaddr_in serv_addr, cli_addr; + int ret = 0; + int opt = 1; + + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) { + IOT_ERROR("ERROR opening socket"); + ret = -1; + goto exit; + } + + if((setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof(opt))) < 0){ + IOT_ERROR("ERROR on setting socket option"); + ret = -1; + goto exit; + } + + memset((char *)&serv_addr, 0, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_len = sizeof(serv_addr); + serv_addr.sin_addr.s_addr = INADDR_ANY; + serv_addr.sin_port = htons(PORT); + + if ((bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) < 0) { + IOT_ERROR("ERROR on binding"); + ret = -1; + goto exit; + } + if ((listen(sockfd, 5)) < 0){ + IOT_ERROR("ERROR on listening tcp server socket fd"); + ret = -1; + goto exit; + } + clilen = sizeof(cli_addr); + newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, (socklen_t*)&clilen); + if (newsockfd < 0) { + IOT_ERROR("ERROR on accept"); + ret = -1; + goto exit2; + } + ret = read(newsockfd, rx_buffer, MAX_BUFFER_SIZE); + if (ret <= 0){ + IOT_ERROR("ERROR reading from socket"); + ret = -1; + goto exit2; + } + IOT_DEBUG("Request received: %s, byte: %d\r\n",rx_buffer, ret); + if(handshake == 1){ + if(strncmp(rx_buffer,"PAIR", strlen("PAIR")) != 0){ + write(newsockfd, "ERROR", strlen("ERROR")); + IOT_ERROR("ERROR on first handshake!"); + ret = -1; + goto exit2; + } + } + else if(handshake == 2){ + if((rx_buffer == NULL) ||(strlen(rx_buffer) < 32)){ + write(newsockfd, "ERROR", strlen("ERROR")); + IOT_ERROR("ERROR on second handshake!"); + ret = -1; + goto exit2; + } + } + else if(handshake == 3){ + unsigned char account[64]; + unsigned char enc_acc[64]; + char *result = NULL, *backup = NULL; + unsigned char *data = NULL; + char *delims = ", "; + int j, k = 1; + if (!strncmp(rx_buffer, "[", strlen("["))){ + data = rx_buffer + strlen("["); + for(j = 1; j < 5; j++){ + if (data[ret - j] == ']') + data[ret -j] = '\0'; + } + } + else + strcpy(data, rx_buffer); + memset(enc_acc, 0, sizeof(enc_acc)); + result = strtok_r(data, delims, &backup); + enc_acc[0]=(uint8_t)atoi(result); + while((result = strtok_r(NULL, delims, &backup)) != NULL) + enc_acc[k++]=(uint8_t)atoi(result); + IOT_DEBUG("The value of k: %d", k); + memset(account, 0, sizeof(account)); + decrypt_data_aes(enc_acc, account, k); + + if((strncmp(account,"https://", strlen("https://"))) != 0){ + write(newsockfd, "ERROR", strlen("ERROR")); + IOT_ERROR("ERROR on third handshake!"); + ret = -1; + goto exit2; + } + else{ + IOT_DEBUG("The received Firebase URL:%s", account); + memset(rx_buffer, 0, strlen(rx_buffer)); + memcpy(rx_buffer, (account+strlen("https://")), (strlen(account) + strlen("https://"))); + } + } + ret = write(newsockfd, tx_buffer, strlen(tx_buffer)); + IOT_DEBUG("Data send: %s\r\n",tx_buffer); + + if (ret < 0){ + IOT_ERROR("ERROR writing to socket"); + } + +exit: + if(close(newsockfd) != 0) + goto exit; + +exit2: + if(close(sockfd) != 0) + goto exit2; + return ret; + +} + +static void pair_device_task(void) +{ + int i, j, k, HANDSHAKE; + uint8_t PAIR_STATE[1] = {0}; + + if(CONTROL_TYPE == 1){ + printf("\r\n\r\n<<<<<>>>>>\r\n\r\n"); + HANDSHAKE = 3; + } + else{ + printf("\r\n\r\n<<<<<>>>>>\r\n\r\n"); + HANDSHAKE = 2; + } + printf("\r\n\r\n=========>PAIR_STATE = 0 Start to pair\r\n\r\n"); + for(i = 0; i < HANDSHAKE; i++){ + static const uint8_t basepoint[32] = {9}; + uint8_t mysecret[32]; + uint8_t mypublic[32]; + uint8_t theirpublic[32] = {0}; + uint8_t shared_key[32]; +//First handshake + if(i == 0){ + printf("\r\n\r\n===>Start the first handshake\r\n\r\n"); + memset(tx_buffer, 0, sizeof(tx_buffer)); + memset(rx_buffer, 0, sizeof(rx_buffer)); + for(j = 0; j < 32; j ++) + mysecret[j] = (uint8_t) arc4random(); + mysecret[j] = '\0'; + curve25519_donna(mypublic, mysecret, basepoint); + for (j = 0; j < 32; j++){ + char *temp; + temp = iot_itoa(mypublic[j]); + if(j == 0) + strcpy(tx_buffer, "["); + strcat(tx_buffer,temp); + if (j == 31) + strcat(tx_buffer,"]"); + else + strcat(tx_buffer,","); + free(temp); + temp = NULL; + } + if(pair_device(tx_buffer, rx_buffer, 1) >= 0) + printf("\r\n\r\n<===First handshake OK!!\r\n\r\n"); + else{ + i--; + printf("\r\n\r\n<===First handshake FAILED!!\r\n\r\n"); + } + } +//Second handshake + if(i == 1){ + printf("\r\n\r\n=====>Start the second handshake\r\n\r\n"); + vTaskDelay(200); + memset(tx_buffer, 0, sizeof(tx_buffer)); + if(CONTROL_TYPE == 1) + memcpy(tx_buffer, "FIREBASE URL", sizeof("FIREBASE URL")); + else + memcpy(tx_buffer, "PAIR OK", sizeof("PAIR OK")); + memset(rx_buffer, 0, sizeof(rx_buffer)); + + if(pair_device(tx_buffer, rx_buffer, 2) >= 0){ + char *result = NULL, *backup = NULL; + unsigned char *data = NULL; + char *delims = ", "; + k = 1; + if (!strncmp(rx_buffer, "[", strlen("["))){ + data = rx_buffer + strlen("["); + int len; + len = strlen(data); + for(j = 1; j < 5; j++){ + if (data[len - j] == ']') + data[len -j] = '\0'; + } + } + else + strcpy(data, rx_buffer); + + memset(theirpublic, 0, sizeof(theirpublic)); + + result = strtok_r(data, delims, &backup); + theirpublic[0]=(uint8_t)atoi(result); + + while((result = strtok_r(NULL, delims, &backup)) != NULL) + theirpublic[k++] = (uint8_t)atoi(result); + + curve25519_donna(shared_key, mysecret, theirpublic); + for(j = 0; j < 16; j ++) + aes_key[j] = shared_key[j]; +//Store the KEY in FLASH + if(CONTROL_TYPE == 0){ + PAIR_STATE[0] = 1; + uint8_t data[33]; + memset(data, 0, 33); + memcpy(data, PAIR_STATE, 1); + memcpy(data+1, shared_key, 32); + flash_erase_sector(&iot_flash, FLASH_IOT_DATA); + flash_stream_write(&iot_flash, FLASH_IOT_DATA, 33, (uint8_t *) data); + IOT_DEBUG("PAIR_STATE: %d\r\n", PAIR_STATE[0]); + } + printf("\r\n\r\n<=====Second handshake OK!!\r\n\r\n"); + } + else{ + i = i - 2; + printf("\r\n\r\n<=====Second handshake FAILED!!\r\n\r\n"); + } + } +//Third handshake + if(i == 2){ + printf("\r\n\r\n=======>Start the third handshake\r\n\r\n"); + vTaskDelay(200); + + memset(tx_buffer, 0, sizeof(tx_buffer)); + memcpy(tx_buffer, "PAIR OK", sizeof("PAIR OK")); + memset(rx_buffer, 0, sizeof(rx_buffer)); + + if(pair_device(tx_buffer, rx_buffer, 3) >= 0){ + IOT_DEBUG("rx_buffer: %s, sizeof rx_buffer:%d\r\n", rx_buffer, sizeof(rx_buffer)); + PAIR_STATE[0] = 1; + uint8_t data[97]; + memset(data, 0, 97); + memcpy(data, PAIR_STATE, 1); + memcpy(data+1, shared_key, 32); + memcpy(data+33, rx_buffer, 64); + flash_erase_sector(&iot_flash, FLASH_IOT_DATA); + flash_stream_write(&iot_flash, FLASH_IOT_DATA, 97, (uint8_t *) data); + IOT_DEBUG("PAIR_STATE: %d\r\n", PAIR_STATE[0]); + + printf("\r\n\r\n<=======Third handshake OK!!\r\n\r\n"); + } + else{ + i = i - 3; + printf("\r\n\r\n<=======Third handshake FAILED!!\r\n\r\n"); + } + } + } + printf("\r\n\r\n<=========Pairing OK!!\r\n\r\n"); +} + +static void mdns_task(void *param) +{ + DNSServiceRef dnsServiceRef = NULL; + TXTRecordRef txtRecord; + unsigned char txt_buf[128]; + uint8_t *mac, *ip; + int j, ret = 0; + uint8_t *flash_data; + uint8_t PAIR_STATE[1] = {0}; + static unsigned char MAC_ADD[21]; + static unsigned char IP[16]; + static unsigned char port[6]; + uint16_t shtc1_id; + +// Delay to wait for IP by DHCP and get the information of IP and MAC + printf("\n\r\n\r\n\r\n\r<<<<<>>>>>>\n\r\n\r\n\r\n\r"); + vTaskDelay(20000); + ip = LwIP_GetIP(&xnetif[0]); + mac = LwIP_GetMAC(&xnetif[0]); + + sprintf(MAC_ADD, "%02x%02x%02x%02x%02x%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + sprintf(IP, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); + sprintf(port, "%d", PORT); + + IOT_DEBUG("MAC => %s\r\n", MAC_ADD) ; + IOT_DEBUG("IP => %s\r\n", IP); + IOT_DEBUG("PORT => %s\r\n", port); + +//Get the value of PAIR_STATE and the AES key in flash + flash_data = (uint8_t *)malloc(33); + flash_stream_read(&iot_flash, FLASH_IOT_DATA, 33, (uint8_t *)flash_data); + memcpy(PAIR_STATE, flash_data, 1); + if(PAIR_STATE[0] != 0x1) + PAIR_STATE[0] = 0; + else{ + for(j = 0;j < 16; j++){ + aes_key[j] = flash_data[j+1]; + } + } + free(flash_data); + IOT_DEBUG("PAIR_STATE now: %d\r\n", PAIR_STATE[0]); + + IOT_DEBUG("=>mDNS Init\r\n"); + if(mDNSResponderInit() == 0) { + printf("\r\n\r\n========>Start to register mDNS service\r\n\r\n"); +//The device not paired before + if(PAIR_STATE[0] == 0){ + TXTRecordCreate(&txtRecord, sizeof(txt_buf), txt_buf); + + TXTRecordSetValue(&txtRecord, "IP", strlen(IP), IP); + TXTRecordSetValue(&txtRecord, "PORT", strlen(port), port); + TXTRecordSetValue(&txtRecord, "MAC_ADDR", strlen(MAC_ADD), MAC_ADD); + TXTRecordSetValue(&txtRecord, "PAIR_STATE", strlen("0"), "0"); + TXTRecordSetValue(&txtRecord, "SERVICE_NAME", strlen("ht_sensor"), "ht_sensor"); + if(CONTROL_TYPE == 1) + TXTRecordSetValue(&txtRecord, "CONTROL_TYPE", strlen("1"), "1"); + else + TXTRecordSetValue(&txtRecord, "CONTROL_TYPE", strlen("0"), "0"); + dnsServiceRef = mDNSRegisterService("ht_sensor", "_Ameba._tcp", "local", PORT, &txtRecord); + TXTRecordDeallocate(&txtRecord); + printf("\r\n\r\n<========Registering mDNS service OK!!\r\n\r\n"); + pair_device_task(); + } +//The device was paired + else if(PAIR_STATE[0] == 0x1){ + TXTRecordCreate(&txtRecord, sizeof(txt_buf), txt_buf); + + TXTRecordSetValue(&txtRecord, "IP", strlen(ip), ip); + TXTRecordSetValue(&txtRecord, "PORT", strlen(port), port); + TXTRecordSetValue(&txtRecord, "MAC_ADDR", strlen(MAC_ADD), MAC_ADD); + TXTRecordSetValue(&txtRecord, "PAIR_STATE", strlen("1"), "1"); + TXTRecordSetValue(&txtRecord, "SERVICE_NAME", strlen("ht_sensor"), "ht_sensor"); + if(CONTROL_TYPE == 1) + TXTRecordSetValue(&txtRecord, "CONTROL_TYPE", strlen("1"), "1"); + else + TXTRecordSetValue(&txtRecord, "CONTROL_TYPE", strlen("0"), "0"); + + dnsServiceRef = mDNSRegisterService("ht_sensor", "_Ameba._tcp", "local", PORT, &txtRecord); + TXTRecordDeallocate(&txtRecord); + printf("\r\n\r\n<========Registering mDNS service OK!! PAIR_STATE = 1\r\n\r\n"); + } +#if PSEUDO_DATA + printf("\r\n\r\n========>Using the speudo data\r\n\r\n"); + if(CONTROL_TYPE == 1) start_cloud_link(); + start_local_link(); +#else +//Init the shtc1 sensor + printf("\r\n\r\n========>Init the temperature and humidity sensor\r\n\r\n"); + ret = SHTC_Init(&shtc1_id); + if ( ret == NO_ERROR ){ + printf("\r\n\r\n<========Senser init OK! ID = 0x%x \r\n\r\n", shtc1_id); + if(CONTROL_TYPE == 1) start_cloud_link(); + start_local_link(); + } + else { + printf("\r\n\r\n<========Senser init FAILED! ID = 0x%x \r\n\r\n", shtc1_id); + ret = -1; + } +#endif + + } + else + ret = -1; + if(ret == 0){ + while(1){ + IOT_DEBUG("Update the mDNS textrecord!\r\n"); + TXTRecordCreate(&txtRecord, sizeof(txt_buf), txt_buf); + TXTRecordSetValue(&txtRecord, "IP", strlen(IP), IP); + TXTRecordSetValue(&txtRecord, "PORT", strlen(port), port); + TXTRecordSetValue(&txtRecord, "MAC_ADDR", strlen(MAC_ADD), MAC_ADD); + TXTRecordSetValue(&txtRecord, "PAIR_STATE", strlen("1"), "1"); + if(CONTROL_TYPE == 1) + TXTRecordSetValue(&txtRecord, "CONTROL_TYPE", strlen("1"), "1"); + else + TXTRecordSetValue(&txtRecord, "CONTROL_TYPE", strlen("0"), "0"); + TXTRecordSetValue(&txtRecord, "SERVICE_NAME", strlen("ht_sensor"), "ht_sensor"); + + mDNSUpdateService(dnsServiceRef, &txtRecord, 0); + TXTRecordDeallocate(&txtRecord); + vTaskDelay(2*60*1000); + } + } + else{ + if(dnsServiceRef) + mDNSDeregisterService(dnsServiceRef); + IOT_DEBUG("<=mDNS Deinit\r\n\r\n"); + mDNSResponderDeinit(); + } +} + +void example_wigadget(void) +{ + if(xTaskCreate(mdns_task, ((const char*)"mdns_task"), 3072, NULL, tskIDLE_PRIORITY + 1, NULL) != pdPASS) + printf("\n\r%s xTaskCreate failed", __FUNCTION__); + + gpio_t gpio_softap_reset_button; + gpio_irq_t gpioirq_softap_reset_button; + + gpio_irq_init(&gpioirq_softap_reset_button, GPIO_SOFTAP_RESET_PIN, iotapp_reset_irq_handler, (uint32_t)(&gpio_softap_reset_button)); + gpio_irq_set(&gpioirq_softap_reset_button, IRQ_FALL, 1); + gpio_irq_enable(&gpioirq_softap_reset_button); +} + diff --git a/component/common/application/wigadget/wigadget.h b/component/common/application/wigadget/wigadget.h new file mode 100644 index 0000000..ae4eb9d --- /dev/null +++ b/component/common/application/wigadget/wigadget.h @@ -0,0 +1,11 @@ +#ifndef WIGADGET_H +#define WIGADGET_H + +#define FLASH_IOT_DATA (0x0007E000) +#define PSEUDO_DATA 1 + +void example_wigadget(void); +void gen_json_data(char *i, char *j, unsigned char *json_data); + +#endif /* WIGADGET_H */ + diff --git a/component/common/application/xmodem/uart_fw_update.c b/component/common/application/xmodem/uart_fw_update.c new file mode 100644 index 0000000..298e1dc --- /dev/null +++ b/component/common/application/xmodem/uart_fw_update.c @@ -0,0 +1,1073 @@ +/******************************************************************************** + * Copyright (c) 2014, Realtek Semiconductor Corp. + * All rights reserved. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + ******************************************************************************* + */ + +#include "xmport_uart.h" +#include "xmport_loguart.h" +#include "rtl8195a.h" +#include "xmodem.h" +#include "xmport_uart.h" +#include "hal_spi_flash.h" +#include "rtl8195a_spi_flash.h" +#include + +#if /*CONFIG_PERI_UPDATE_IMG*/1 + +#define IMG1_SIGN_OFFSET 0x34 + +enum { + XMODEM_UART_0 = 0, + XMODEM_UART_1 = 1, + XMODEM_UART_2 = 2, + XMODEM_LOG_UART = 3 +}; + +FWU_DATA_SECTION char xMFrameBuf[XM_BUFFER_SIZE]; +FWU_DATA_SECTION XMODEM_CTRL xMCtrl; + +FWU_DATA_SECTION static u32 fw_img1_size; +FWU_DATA_SECTION static u32 fw_img2_size; +FWU_DATA_SECTION static u32 fw_img2_addr; +FWU_DATA_SECTION static u32 fw_img3_size; +FWU_DATA_SECTION static u32 fw_img3_addr; +FWU_DATA_SECTION static u32 flash_wr_offset; +FWU_DATA_SECTION static u32 flash_erased_addr; +FWU_DATA_SECTION static u8 start_with_img1; +FWU_DATA_SECTION static u32 flash_wr_err_cnt; + +FWU_DATA_SECTION HAL_RUART_ADAPTER xmodem_uart_adp; // we can dynamic allocate memory for this object to save memory + +FWU_RODATA_SECTION const char Img2Signature[8]="81958711"; +extern u32 SpicCalibrationPattern[4]; +extern const u8 ROM_IMG1_VALID_PATTEN[]; +extern HAL_RUART_ADAPTER *pxmodem_uart_adp; + +#ifdef CONFIG_GPIO_EN +extern HAL_GPIO_ADAPTER gBoot_Gpio_Adapter; +extern PHAL_GPIO_ADAPTER _pHAL_Gpio_Adapter; +#endif + +extern BOOLEAN SpicFlashInitRtl8195A(u8 SpicBitMode); +_LONG_CALL_ +extern VOID SpicWaitBusyDoneRtl8195A(VOID); +extern VOID SpicWaitWipDoneRefinedRtl8195A(SPIC_INIT_PARA SpicInitPara); + +VOID WriteImg1Sign(u32 Image2Addr); + +FWU_TEXT_SECTION void FWU_WriteWord(u32 Addr, u32 FData) +{ + SPIC_INIT_PARA SpicInitPara; + + HAL_WRITE32(SPI_FLASH_BASE, Addr, FData); + // Wait spic busy done + SpicWaitBusyDoneRtl8195A(); + // Wait flash busy done (wip=0) + SpicWaitWipDoneRefinedRtl8195A(SpicInitPara); +} + +FWU_TEXT_SECTION u32 xModem_MemCmp(const u32 *av, const u32 *bv, u32 len) +{ + const u32 *a = av; + const u32 *b = (u32*)((u8*)bv+SPI_FLASH_BASE); + u32 len4b = len >> 2; + u32 i; + + for (i=0; i 0) && (idx < frame_size)) { + flash_wr_offset--; + idx++; + skip_sz++; + } + + // "fw_img2_size" here is used as the memory length to write + // "fw_img2_addr" is used as the start memory address to write + while (idx < frame_size) { + if (fw_img2_size == 0) { + return idx; + } + + if (((fw_img2_addr & 0x03) == 0) && + (fw_img2_size > 3) && + ((frame_size - idx) > 3)) { + // write address is 4-byte aligned + *((u32*)fw_img2_addr) = (*((u32*)(ptr+idx))); + fw_img2_addr += 4; + fw_img2_size -= 4; + idx += 4; + } else if (fw_img2_size > 0){ + *((u8*)fw_img2_addr) = (*((u8*)(ptr+idx))); + fw_img2_addr++; + fw_img2_size--; + idx++; + } + } + + return (idx - skip_sz); +} + +FWU_TEXT_SECTION +u32 xModem_Frame_FlashWrite(char *ptr, unsigned int frame_num, unsigned int frame_size) +{ + u32 idx=0; + u32 skip_sz=0; + u32 temp; + u32 i; + + // "flash_wr_offset" here is used as the skip bytes from the head + while ((flash_wr_offset > 0) && (idx < frame_size)) { + flash_wr_offset--; + idx++; + skip_sz++; + } + + // "fw_img2_size" here is used as the memory length to write + // "fw_img2_addr" is used as the start memory address to write + while (idx < frame_size) { + if (fw_img2_size == 0) { + return idx; + } + + if ((fw_img2_size > 3) && ((frame_size - idx) > 3)) { + FWU_WriteWord(fw_img2_addr, (*((u32*)(ptr+idx)))); + fw_img2_addr += 4; + fw_img2_size -= 4; + idx += 4; + } else { + temp = 0xFFFFFFFF; + for (i=0;i<4;i++) { + // Just for little endian + *((((u8*)&temp) + i)) = (*((u8*)(ptr+idx))); + idx++; + fw_img2_size--; + if ((fw_img2_size == 0) || (idx >= frame_size)) { + break; + } + } + FWU_WriteWord(fw_img2_addr, temp); + fw_img2_addr += 4; + } + } + + return (idx - skip_sz); +} + +FWU_TEXT_SECTION +u32 xModem_Frame_Img2(char *ptr, unsigned int frame_num, unsigned int frame_size) +{ + u32 address; + u32 ImageIndex=0; + u32 rx_len=0; + u32 *chk_sr; + u32 *chk_dr; + u32 err_addr; + + if (frame_num == 1) { + // Parse Image2 header + flash_wr_offset = fw_img2_addr; + fw_img2_size = rtk_le32_to_cpu(*((u32*)ptr)) + 0x10; + if ((fw_img2_size & 0x03) != 0) { + DBG_MISC_ERR("xModem_Frame_ImgAll Err#2: fw_img2_addr=0x%x fw_img2_size(%d) isn't 4-bytes aligned\r\n", fw_img2_addr, fw_img2_size); + fw_img1_size = 0; + fw_img2_size = 0; + return rx_len; + } + + if (fw_img2_size > (2*1024*1024)) { + DBG_MISC_ERR("xModem_Frame_ImgAll Image2 to Big: fw_img2_addr=0x%x fw_img2_size(%d) \r\n", fw_img2_addr, fw_img2_size); + fw_img1_size = 0; + fw_img2_size = 0; + return rx_len; + } + fw_img3_addr = fw_img2_addr + fw_img2_size; + + // erase Flash first + address = fw_img2_addr & (~0xfff); // 4k aligned, 4k is the page size of flash memory + while ((address) < (fw_img2_addr+fw_img2_size)) { + SpicSectorEraseFlashRtl8195A(SPI_FLASH_BASE + address); + address += 0x1000; + } + flash_erased_addr = address; + } + + if (fw_img2_size > 0) { + // writing image2 + chk_sr = (u32*)((u8*)ptr+ImageIndex); + chk_dr = (u32*)flash_wr_offset; + while (ImageIndex < frame_size) { + FWU_WriteWord(flash_wr_offset, (*((u32*)(ptr+ImageIndex)))); + ImageIndex += 4; + flash_wr_offset += 4; + rx_len += 4; + fw_img2_size -= 4; + if (fw_img2_size == 0) { + // Image2 write done, + break; + } + } + + err_addr = xModem_MemCmp(chk_sr, chk_dr, (flash_wr_offset - (u32)chk_dr)); + if (err_addr) { + flash_wr_err_cnt++; + } + } + + if (ImageIndex >= frame_size) { + return rx_len; + } + + // Skip the gap between image2 and image3, + // there is no gap in current image format + if (flash_wr_offset < fw_img3_addr) { + if ((flash_wr_offset + (frame_size-ImageIndex)) <= fw_img3_addr) { + flash_wr_offset += (frame_size-ImageIndex); + return rx_len; + } else { + while (ImageIndex < frame_size) { + if (flash_wr_offset == fw_img3_addr) { + break; + } + ImageIndex += 4; + flash_wr_offset += 4; + } + } + } + + if (fw_img3_addr == flash_wr_offset) { + if (ImageIndex < frame_size) { + fw_img3_size = rtk_le32_to_cpu(*((u32*)(ptr+ImageIndex))); + if (fw_img3_size == 0x1A1A1A1A) { + // all padding bytes, no image3 + fw_img3_size = 0; + return rx_len; + } + if ((fw_img3_size & 0x03) != 0) { + DBG_MISC_ERR("xModem_Frame_ImgAll Err#5: fw_img3_addr=0x%x fw_img3_size(%d) isn't 4-bytes aligned\r\n", fw_img3_addr, fw_img3_size); + fw_img3_size = 0; + return rx_len; + } + + if (fw_img3_size > (2*1024*1024)) { + DBG_MISC_ERR("xModem_Frame_ImgAll Image3 to Big: fw_img3_addr=0x%x fw_img2_size(%d) \r\n", fw_img3_addr, fw_img3_size); + fw_img3_size = 0; + return rx_len; + } + + // Flash sector erase for image2 writing + if (flash_erased_addr >= fw_img3_addr) { + address = flash_erased_addr; + } else { + address = fw_img3_addr & (~0xfff); // 4k aligned, 4k is the page size of flash memory + } + + while ((address) < (fw_img3_addr+fw_img3_size)) { + DBG_MISC_INFO("Flash Erase: 0x%x\n", address); +#if 0 + if ((address & 0xFFFF) == 0) { + SpicBlockEraseFlashRtl8195A(SPI_FLASH_BASE + address); + address += 0x10000; // 1 block = 64k bytes + } + else +#endif + { + SpicSectorEraseFlashRtl8195A(SPI_FLASH_BASE + address); + address += 0x1000; // 1 sector = 4k bytes + } + } + flash_erased_addr = address; + } + } + + if (fw_img3_size > 0) { + // writing image3 + chk_sr = (u32*)((u8*)ptr+ImageIndex); + chk_dr = (u32*)flash_wr_offset; + while (ImageIndex < frame_size) { + FWU_WriteWord(flash_wr_offset, (*((u32*)(ptr+ImageIndex)))); + ImageIndex += 4; + flash_wr_offset += 4; + rx_len += 4; + fw_img3_size -= 4; + if (fw_img3_size == 0) { + // Image3 write done, + break; + } + } + + err_addr = xModem_MemCmp(chk_sr, chk_dr, (flash_wr_offset - (u32)chk_dr)); + if (err_addr) { + flash_wr_err_cnt++; + } + } + + return rx_len; +} + +FWU_TEXT_SECTION +u32 xModem_Frame_ImgAll(char *ptr, unsigned int frame_num, unsigned int frame_size) +{ + int i; + u32 address; + u32 img_size; + u32 img_addr; + u32 ImgIdx=0; + u32 Img1Sign; + u32 rx_len=0; + u32 *chk_sr; + u32 *chk_dr; + u32 err_addr; + + if (frame_num == 1) { + // Check is it the start patten of image1 + start_with_img1 = 1; + for(i=0; i<4; i++) { + Img1Sign = rtk_le32_to_cpu(*((u32*)(ptr + i*4))); + if(Img1Sign != SpicCalibrationPattern[i]) { + start_with_img1 = 0; + break; + } + } + + // Get the image size: the first 4 bytes + if (start_with_img1) { + // Image1 + Image2 + // Check the Image1 Signature + i=0; + while (ROM_IMG1_VALID_PATTEN[i] != 0xff) { + if (ptr[i+IMG1_SIGN_OFFSET] != ROM_IMG1_VALID_PATTEN[i]) { + // image1 validation patten miss match + DBG_MISC_ERR("xModem_Frame_ImgAll Err: Image1 Signature Incorrect\r\n"); + fw_img1_size = 0; + fw_img2_size = 0; + fw_img2_addr = 0; + fw_img3_size = 0; + fw_img3_addr = 0; + return 0; + } else { + // make the signature all 0xff for now, write the signature when image1 download is done + ptr[i+IMG1_SIGN_OFFSET] = 0xff; + } + i++; + } + + flash_wr_offset = 0; + fw_img1_size = rtk_le32_to_cpu(*((u32*)(ptr + 0x10))) + 0x20; + if ((fw_img1_size & 0x03) != 0) { + DBG_MISC_WARN("xModem_Frame_ImgAll Err: fw_img1_size(0x%x) isn't 4-bytes aligned\r\n", fw_img1_size); + fw_img1_size = 0; + fw_img2_size = 0; + fw_img2_addr = 0; + fw_img3_size = 0; + fw_img3_addr = 0; + return 0; + } + address = 0; + img_size = fw_img1_size; + img_addr = 0; + fw_img2_addr = rtk_le16_to_cpu(*((u16*)(ptr + 0x18))) * 1024; + if (fw_img2_addr == 0) { + // it's old format: image1 & image2 is cascaded directly + fw_img2_addr = fw_img1_size; + } + fw_img2_size = 0; + DBG_MISC_INFO("Update Image All: Image1 Size=%d, Image2 Addr=0x%x\r\n", fw_img1_size, fw_img2_addr); + } else { + // It's image2(+image3) only + if (fw_img2_addr == 0) { + DBG_MISC_WARN("The single-image format in flash now, it cannot just update the image2\r\n"); + fw_img1_size = 0; + fw_img2_size = 0; + return rx_len; + } + + flash_wr_offset = fw_img2_addr; + fw_img1_size = 0; + fw_img2_size = rtk_le32_to_cpu(*((u32*)ptr)) + 0x10; + fw_img3_addr = fw_img2_addr + fw_img2_size; + if ((fw_img2_size & 0x03) != 0) { + DBG_MISC_ERR("xModem_Frame_ImgAll Err: fw_img2_size(0x%x) isn't 4-bytes aligned\r\n", fw_img2_size); + fw_img1_size = 0; + fw_img2_size = 0; + return rx_len; + } + address = fw_img2_addr & (~0xfff); // 4k aligned, 4k is the page size of flash memory + img_size = fw_img2_size; + img_addr = fw_img2_addr; + + DBG_MISC_INFO("Update Image2: Addr=0x%x, Size=%d\r\n", fw_img2_addr, fw_img2_size); + + } + + // erase Flash sector first + while ((address) < (img_addr+img_size)) { +// DBG_MISC_INFO("Flash Erase: 0x%x\n", address); + if ((address >= 0x10000 ) && ((address & 0xFFFF) == 0)) { + SpicBlockEraseFlashRtl8195A(SPI_FLASH_BASE + address); + address += 0x10000; // 1 Block = 64k bytes + } + else + { + SpicSectorEraseFlashRtl8195A(SPI_FLASH_BASE + address); + address += 0x1000; // 1 sector = 4k bytes + } + } + flash_erased_addr = address; + } + + { + if (!start_with_img1) { + if (fw_img2_size > 0) { + chk_sr = (u32*)((u8*)ptr+ImgIdx); + chk_dr = (u32*)flash_wr_offset; + while (ImgIdx < frame_size) { + FWU_WriteWord(flash_wr_offset, (*((u32*)(ptr+ImgIdx)))); + ImgIdx += 4; + flash_wr_offset += 4; + rx_len += 4; + fw_img2_size -= 4; + if (fw_img2_size == 0) { + break; + } + + } + err_addr = xModem_MemCmp(chk_sr, chk_dr, (flash_wr_offset - (u32)chk_dr)); + if (err_addr) { + flash_wr_err_cnt++; + } + } + } else { + ImgIdx = 0; + if (fw_img1_size > 0) { + // still writing image1 + chk_sr = (u32*)((u8*)ptr+ImgIdx); + chk_dr = (u32*)flash_wr_offset; + while (ImgIdx < frame_size) { + FWU_WriteWord(flash_wr_offset, (*((u32*)(ptr+ImgIdx)))); + ImgIdx += 4; + flash_wr_offset += 4; + rx_len += 4; + fw_img1_size -= 4; + if (fw_img1_size == 0) { + // Image1 write done, + break; + } + } + + err_addr = xModem_MemCmp(chk_sr, chk_dr, (flash_wr_offset - (u32)chk_dr)); + if (err_addr) { + flash_wr_err_cnt++; + } else { + if (fw_img1_size == 0) { + // Write Image1 signature + WriteImg1Sign(IMG1_SIGN_OFFSET); + } + } + } + + if (ImgIdx >= frame_size) { + return rx_len; + } + + if (fw_img2_addr == 0) { + return rx_len; + } + + // Skip the section of system data + if (flash_wr_offset < fw_img2_addr) { + if ((flash_wr_offset + (frame_size-ImgIdx)) <= fw_img2_addr) { + flash_wr_offset += (frame_size-ImgIdx); + return rx_len; + } else { + while (ImgIdx < frame_size) { + if (flash_wr_offset == fw_img2_addr) { + break; + } + ImgIdx += 4; + flash_wr_offset += 4; + rx_len += 4; + } + } + } + + if (fw_img2_addr == flash_wr_offset) { + if (ImgIdx < frame_size) { + fw_img2_size = rtk_le32_to_cpu(*((u32*)(ptr+ImgIdx))) + 0x10; + fw_img3_addr = fw_img2_addr + fw_img2_size; + if ((fw_img2_size & 0x03) != 0) { + DBG_MISC_ERR("xModem_Frame_ImgAll Err#2: fw_img2_addr=0x%x fw_img2_size(%d) isn't 4-bytes aligned\r\n", fw_img2_addr, fw_img2_size); + fw_img1_size = 0; + fw_img2_size = 0; + return rx_len; + } + + if (fw_img2_size > (2*1024*1024)) { + DBG_MISC_ERR("xModem_Frame_ImgAll Image2 to Big: fw_img2_addr=0x%x fw_img2_size(%d) \r\n", fw_img2_addr, fw_img2_size); + fw_img1_size = 0; + fw_img2_size = 0; + return rx_len; + } + + // Flash sector erase for image2 writing + if (flash_erased_addr >= fw_img2_addr) { + address = flash_erased_addr; + } else { + address = fw_img2_addr & (~0xfff); // 4k aligned, 4k is the page size of flash memory + } + + while ((address) < (fw_img2_addr+fw_img2_size)) { + DBG_MISC_INFO("Flash Erase: 0x%x\n", address); + if ((address & 0xFFFF) == 0) { + SpicBlockEraseFlashRtl8195A(SPI_FLASH_BASE + address); + address += 0x10000; // 1 block = 64k bytes + } + else + { + SpicSectorEraseFlashRtl8195A(SPI_FLASH_BASE + address); + address += 0x1000; // 1 sector = 4k bytes + } + } + flash_erased_addr = address; + } + } + + if (fw_img2_size > 0) { + // writing image2 + chk_sr = (u32*)((u8*)ptr+ImgIdx); + chk_dr = (u32*)flash_wr_offset; + while (ImgIdx < frame_size) { + FWU_WriteWord(flash_wr_offset, (*((u32*)(ptr+ImgIdx)))); + ImgIdx += 4; + flash_wr_offset += 4; + rx_len += 4; + fw_img2_size -= 4; + if (fw_img2_size == 0) { + // Image2 write done, + break; + } + } + + err_addr = xModem_MemCmp(chk_sr, chk_dr, (flash_wr_offset - (u32)chk_dr)); + if (err_addr) { + flash_wr_err_cnt++; + } + } + + if (ImgIdx >= frame_size) { + return rx_len; + } + + if (fw_img3_addr == flash_wr_offset) { + if (ImgIdx < frame_size) { + fw_img3_size = rtk_le32_to_cpu(*((u32*)(ptr+ImgIdx))); + if (fw_img3_size == 0x1A1A1A1A) { + // all padding bytes, no image3 + fw_img3_size = 0; +// DBG_8195A("No Img3\r\n"); + return rx_len; + } + if ((fw_img3_size & 0x03) != 0) { + DBG_MISC_ERR("xModem_Frame_ImgAll Err#5: fw_img3_addr=0x%x fw_img3_size(%d) isn't 4-bytes aligned\r\n", fw_img3_addr, fw_img3_size); + fw_img3_size = 0; + return rx_len; + } + + if (fw_img3_size > (2*1024*1024)) { + DBG_MISC_ERR("xModem_Frame_ImgAll Image3 to Big: fw_img3_addr=0x%x fw_img2_size(%d) \r\n", fw_img3_addr, fw_img3_size); + fw_img3_size = 0; + return rx_len; + } + + // Flash sector erase for image2 writing + if (flash_erased_addr >= fw_img3_addr) { + address = flash_erased_addr; + } else { + address = fw_img3_addr & (~0xfff); // 4k aligned, 4k is the page size of flash memory + } + + while ((address) < (fw_img3_addr+fw_img3_size)) { + DBG_MISC_INFO("Flash Erase: 0x%x\n", address); + if ((address & 0xFFFF) == 0) { + SpicBlockEraseFlashRtl8195A(SPI_FLASH_BASE + address); + address += 0x10000; // 1 block = 64k bytes + } + else + { + SpicSectorEraseFlashRtl8195A(SPI_FLASH_BASE + address); + address += 0x1000; // 1 sector = 4k bytes + } + } + flash_erased_addr = address; + } + } + + if (fw_img3_size > 0) { + // writing image3 + chk_sr = (u32*)((u8*)ptr+ImgIdx); + chk_dr = (u32*)flash_wr_offset; + while (ImgIdx < frame_size) { + FWU_WriteWord(flash_wr_offset, (*((u32*)(ptr+ImgIdx)))); + ImgIdx += 4; + flash_wr_offset += 4; + rx_len += 4; + fw_img3_size -= 4; + if (fw_img3_size == 0) { + // Image3 write done, + break; + } + } + err_addr = xModem_MemCmp(chk_sr, chk_dr, (flash_wr_offset - (u32)chk_dr)); + if (err_addr) { + flash_wr_err_cnt++; + } + } + + } + } + + return rx_len; +} + +FWU_TEXT_SECTION +s32 +xModem_Init_UART_Port(u8 uart_idx, u8 pin_mux, u32 baud_rate) +{ + if (uart_idx <= XMODEM_UART_2) { + // update firmware via generic UART + pxmodem_uart_adp = &xmodem_uart_adp; // we can use dynamic allocate to save memory +// pxmodem_uart_adp = RtlZmalloc(sizeof(HAL_RUART_ADAPTER)); + xmodem_uart_init(uart_idx, pin_mux, baud_rate); + xmodem_uart_func_hook(&(xMCtrl.ComPort)); + } else if(uart_idx == XMODEM_LOG_UART) { + // update firmware via Log UART +// DiagPrintf("Open xModem Transfer on Log UART...\r\n"); +// xmodem_loguart_init(); + xmodem_loguart_init(baud_rate); + xmodem_loguart_func_hook(&(xMCtrl.ComPort)); +// DiagPrintf("Please Start the xModem Sender...\r\n"); + } else { + // invalid UART port + DBG_MISC_ERR("xModem_Init_UART_Port: Invaild UART port(%d)\n", uart_idx); + return -1; + } + + return 0; +} + +FWU_TEXT_SECTION +VOID +xModem_DeInit_UART_Port(u8 uart_idx) +{ + if (uart_idx <= XMODEM_UART_2) { + xmodem_uart_deinit(); + } else if (uart_idx == XMODEM_LOG_UART) { + xmodem_loguart_deinit(); + } +} + +FWU_TEXT_SECTION +__weak s32 +UpdatedImg2AddrValidate( + u32 Image2Addr, + u32 DefImage2Addr, + u32 DefImage2Size +) +{ + if (Image2Addr == 0xffffffff) { + // Upgraded Image2 isn't exist + return 0; // invalid address + } + + if ((Image2Addr & 0xfff) != 0) { + // Not 4K aligned + return 0; // invalid address + } + + if (Image2Addr <= DefImage2Addr) { + // Updated image2 address must bigger than the addrss of default image2 + return 0; // invalid address + } + + if (Image2Addr < (DefImage2Addr+DefImage2Size)) { + // Updated image2 overlap with the default image2 + return 0; // invalid address + } + + return 1; // this address is valid +} + +FWU_TEXT_SECTION +__weak s32 +Img2SignValidate( + u32 Image2Addr +) +{ + u32 img2_sig[3]; + s32 sign_valid=0; + + // Image2 header: Size(4B) + Addr(4B) + Signature(8B) + img2_sig[0] = HAL_READ32(SPI_FLASH_BASE, Image2Addr + 8); + img2_sig[1] = HAL_READ32(SPI_FLASH_BASE, Image2Addr + 12); + img2_sig[2] = 0; // end of string + + if (_memcmp((void*)img2_sig, (void*)Img2Signature, 8)) { + DBG_MISC_INFO("Invalid Image2 Signature:%s\n", img2_sig); + } else { + sign_valid = 1; + } + + return sign_valid; + +} + + +FWU_TEXT_SECTION +VOID +MarkImg2SignOld( + u32 Image2Addr +) +{ + u32 img2_sig; + + _memcpy((void*)&img2_sig, (void*)Img2Signature, 4); + *((char*)(&img2_sig)) = '0'; // '8' -> the latest image; '0' -> the older image + FWU_WriteWord((Image2Addr + 8), img2_sig); +} + +FWU_TEXT_SECTION +VOID +WriteImg1Sign( + u32 Image2Addr +) +{ + u32 img1_sig; + + _memcpy((void*)&img1_sig, (void*)ROM_IMG1_VALID_PATTEN, 4); + FWU_WriteWord(IMG1_SIGN_OFFSET, img1_sig); +} + +FWU_TEXT_SECTION +VOID +WriteImg2Sign( + u32 Image2Addr +) +{ + u32 img2_sig[2]; + + _memcpy((void*)img2_sig, (void*)Img2Signature, 8); + FWU_WriteWord((Image2Addr + 8), img2_sig[0]); + FWU_WriteWord((Image2Addr + 12), img2_sig[1]); +} + +FWU_TEXT_SECTION +u32 +SelectImg2ToUpdate( + u32 *OldImg2Addr +) +{ + u32 DefImage2Addr=0xFFFFFFFF; // the default Image2 addr. + u32 SecImage2Addr=0xFFFFFFFF; // the 2nd image2 addr. + u32 ATSCAddr=0xFFFFFFFF; + u32 UpdImage2Addr; // the addr of the image2 to be updated + u32 DefImage2Len; +#ifdef CONFIG_UPDATE_TOGGLE_IMG2 + u32 SigImage0,SigImage1; +#endif + + *OldImg2Addr = 0; + DefImage2Addr = (HAL_READ32(SPI_FLASH_BASE, 0x18)&0xFFFF) * 1024; + if ((DefImage2Addr != 0) && ((DefImage2Addr < (16*1024*1024)))) { + // Valid Default Image2 Addr: != 0 & located in 16M + DefImage2Len = HAL_READ32(SPI_FLASH_BASE, DefImage2Addr); + + // Get the pointer of the upgraded Image2 + SecImage2Addr = HAL_READ32(SPI_FLASH_BASE, FLASH_SYSTEM_DATA_ADDR); + + if (UpdatedImg2AddrValidate(SecImage2Addr, DefImage2Addr, DefImage2Len)) { + UpdImage2Addr = SecImage2Addr; // Update the 2nd image2 +#ifdef CONFIG_UPDATE_TOGGLE_IMG2 + // read Part1/Part2 signature + SigImage0 = HAL_READ32(SPI_FLASH_BASE, DefImage2Addr + 8); + SigImage1 = HAL_READ32(SPI_FLASH_BASE, DefImage2Addr + 12); + + DBG_8195A("\n\rPart1 Sig %x", SigImage0); + if(SigImage0==0x30303030 && SigImage1==0x30303030) + ATSCAddr = DefImage2Addr; // ATSC signature + else if(SigImage0==0x35393138 && SigImage1==0x31313738) + *OldImg2Addr = DefImage2Addr; // newer version, change to older version + else + UpdImage2Addr = DefImage2Addr; // update to older version + + SigImage0 = HAL_READ32(SPI_FLASH_BASE, SecImage2Addr + 8); + SigImage1 = HAL_READ32(SPI_FLASH_BASE, SecImage2Addr + 12); + DBG_8195A("\n\rPart2 Sig %x\n\r", SigImage0); + if(SigImage0==0x30303030 && SigImage1==0x30303030) + ATSCAddr = SecImage2Addr; // ATSC signature + else if(SigImage0==0x35393138 && SigImage1==0x31313738) + *OldImg2Addr = SecImage2Addr; + else + UpdImage2Addr = SecImage2Addr; + + // update ATSC clear partitin first + if(ATSCAddr != ~0x0){ + *OldImg2Addr = UpdImage2Addr; + UpdImage2Addr = ATSCAddr; + } +#endif // end of SWAP_UPDATE, wf, 1006 + } else { + // The upgraded image2 isn't exist or invalid so we can just update the default image2 + UpdImage2Addr = DefImage2Addr; // Update the default image2 + #ifdef CONFIG_UPDATE_TOGGLE_IMG2 + *OldImg2Addr = DefImage2Addr; +#endif + } + } else { + UpdImage2Addr = 0; + } + + return UpdImage2Addr; +} + + +FWU_TEXT_SECTION +void OTU_FW_Update(u8 uart_idx, u8 pin_mux, u32 baud_rate) +{ + u32 wr_len; + u32 OldImage2Addr=0; // the addr of the image2 will become old one + SPIC_INIT_PARA SpicInitPara; + + fw_img1_size = 0; + fw_img2_size = 0; + fw_img2_addr = 0; + fw_img3_size = 0; + fw_img3_addr = 0; + flash_wr_offset = 0; + flash_erased_addr = 0; + start_with_img1 = 0;; + flash_wr_err_cnt = 0; + + // Get the address of the image2 to be updated + SPI_FLASH_PIN_FCTRL(ON); + if (!SpicFlashInitRtl8195A(SpicOneBitMode)){ + SPI_FLASH_PIN_FCTRL(OFF); + DBG_MISC_ERR("OTU_FW_Update: SPI Init Fail!!!!!!\n"); + return; + } + SpicWaitWipDoneRefinedRtl8195A(SpicInitPara); + + printf("FW Update Over UART%d, PinMux=%d, Baud=%d\r\n", uart_idx, pin_mux, baud_rate); + fw_img2_addr = SelectImg2ToUpdate(&OldImage2Addr); + + // Start to update the Image2 through xModem on peripheral device + printf("FW Update Image2 @ 0x%x\r\n", fw_img2_addr); + // We update the image via xModem on UART now, if we want to uase other peripheral device + // to update the image then we need to redefine the API + if (xModem_Init_UART_Port(uart_idx, pin_mux, baud_rate) < 0) { + return; + } + +// xModemStart(&xMCtrl, xMFrameBuf, xModem_Frame_ImgAll); // Support Image format: Image1+Image2 or Image2 only + xModemStart(&xMCtrl, xMFrameBuf, xModem_Frame_Img2); // Support Image format: Image2 only +// xModemStart(&xMCtrl, xMFrameBuf, xModem_Frame_Dump); // for debugging + wr_len = xModemRxBuffer(&xMCtrl, (2*1024*1024)); + xModemEnd(&xMCtrl); + + xModem_DeInit_UART_Port(uart_idx); + + if ((wr_len > 0) && (flash_wr_err_cnt == 0)) { + // Firmware update OK, now write the signature to active this image + WriteImg2Sign(fw_img2_addr); +#ifdef CONFIG_UPDATE_TOGGLE_IMG2 + // Mark the other image2 as old one by modify its signature + if (OldImage2Addr != 0) { + printf("Mark Image2 @ 0x%x as Old\r\n", OldImage2Addr); + MarkImg2SignOld(OldImage2Addr); + } +#endif + } + printf("OTU_FW_Update Done, Write Len=%d\n", wr_len); + SPI_FLASH_PIN_FCTRL(OFF); +} + +FWU_TEXT_SECTION +u8 OTU_check_gpio(void) +{ +#ifdef CONFIG_GPIO_EN + HAL_GPIO_PIN GPIO_Pin; + u8 enter_update; + + GPIO_Pin.pin_name = HAL_GPIO_GetIPPinName_8195a(0x21);; //pin PC_1 + GPIO_Pin.pin_mode = DIN_PULL_HIGH; + + _pHAL_Gpio_Adapter = &gBoot_Gpio_Adapter; + + HAL_GPIO_Init_8195a(&GPIO_Pin); + if (HAL_GPIO_ReadPin_8195a(&GPIO_Pin) == GPIO_PIN_LOW) { + enter_update = 1; + } + else { + enter_update = 0; + } + HAL_GPIO_DeInit_8195a(&GPIO_Pin); + + _pHAL_Gpio_Adapter = NULL; + return enter_update; +#else + return 0; +#endif +} + +FWU_TEXT_SECTION +u8 OTU_check_uart(u32 UpdateImgCfg){ + + if(((UpdateImgCfg>>4)&0x03) == 2){ + ACTCK_SDIOD_CCTRL(OFF); + + /* SDIO Function Disable */ + SDIOD_ON_FCTRL(OFF); + SDIOD_OFF_FCTRL(OFF); + + // SDIO Pin Mux off + SDIOD_PIN_FCTRL(OFF); + } + + if (xModem_Init_UART_Port(((UpdateImgCfg>>4)&0x03), (UpdateImgCfg&0x03), 115200) < 0) { + return 0; + } + + + char ch; + u8 x_count = 0; + int timeout1 = 500; + while (timeout1 != 0) { + if (xMCtrl.ComPort.poll()) { + ch = xMCtrl.ComPort.get(); + if(ch != 0x78){ + xModem_DeInit_UART_Port(((UpdateImgCfg>>4)&0x03)); + return 0; + } + x_count ++; + if(x_count == 5){ + xModem_DeInit_UART_Port(((UpdateImgCfg>>4)&0x03)); + return 1; + } + } + HalDelayUs(200); + timeout1--; + } + + if(!x_count){ + xModem_DeInit_UART_Port(((UpdateImgCfg>>4)&0x03)); + return 0; + } + + int timeout2 = 4500; + while (timeout2 != 0) { + if (xMCtrl.ComPort.poll()) { + ch = xMCtrl.ComPort.get(); + if(ch != 0x78){ + xModem_DeInit_UART_Port(((UpdateImgCfg>>4)&0x03)); + return 0; + } + x_count ++; + if(x_count == 5) + { + xModem_DeInit_UART_Port(((UpdateImgCfg>>4)&0x03)); + return 1; + } + } + HalDelayUs(200); + timeout2--; + } + + xModem_DeInit_UART_Port(((UpdateImgCfg>>4)&0x03)); + return 0; +} + +FWU_TEXT_SECTION +void OTU_Img_Download(u8 uart_idx, u8 pin_mux, u32 baud_rate, + u32 start_offset, u32 start_addr, u32 max_size) +{ + SPIC_INIT_PARA SpicInitPara; + u32 wr_len; + u8 is_flash=0; + + if (xModem_Init_UART_Port(uart_idx, pin_mux, baud_rate) < 0) { + return; + } + + DBG_MISC_INFO("Image Download: StartOffset=%d StartAddr=0x%x MaxSize=%d\r\n", start_offset, start_addr, max_size); + + fw_img2_addr = start_addr; + flash_wr_offset = start_offset; + fw_img2_size = max_size; + + if ((start_addr & 0xFF000000) == SPI_FLASH_BASE) { + // it's going to write the Flash memory + if (((start_addr & 0x03) != 0) || ((start_offset&0x03) != 0)) { + DiagPrintf("StartAddr(0x%x), StartOffset(0x%x) Must 4-bytes Aligned\r\n", start_addr, start_offset); + return; + } + SPI_FLASH_PIN_FCTRL(ON); + if (!SpicFlashInitRtl8195A(SpicOneBitMode)){ + DBG_MISC_ERR("OTU_FW_Update: SPI Init Fail!!!!!!\n"); + SPI_FLASH_PIN_FCTRL(OFF); + return; + } + is_flash = 1; + SpicWaitWipDoneRefinedRtl8195A(SpicInitPara); + fw_img2_addr = start_addr & 0x00FFFFFF; + xModemStart(&xMCtrl, xMFrameBuf, xModem_Frame_FlashWrite); + } else { + xModemStart(&xMCtrl, xMFrameBuf, xModem_Frame_MemWrite); + } + wr_len = xModemRxBuffer(&xMCtrl, ((((max_size+flash_wr_offset-1)>>7)+1) << 7)); + xModemEnd(&xMCtrl); + + xModem_DeInit_UART_Port(uart_idx); + + DBG_MISC_INFO("OTU_Img_Download Done, Write Len=%d\n", wr_len); + + if (is_flash) { + SPI_FLASH_PIN_FCTRL(OFF); + } +} + +#endif //#if CONFIG_PERI_UPDATE_IMG + diff --git a/component/common/application/xmodem/xmodem.h b/component/common/application/xmodem/xmodem.h new file mode 100644 index 0000000..812970c --- /dev/null +++ b/component/common/application/xmodem/xmodem.h @@ -0,0 +1,86 @@ +/* + X-Modem Header File + + 1999/09/03 sprite, support Xmode Tx & Rx +*/ + +#ifndef _XMODE_H_ +#define _XMODE_H_ + +#include + +/***************** + * X-Modem status + *****************/ +#define XMODEM_OK 1 +#define XMODEM_CANCEL 2 +#define XMODEM_ACK 3 +#define XMODEM_NAK 4 +#define XMODEM_COMPLETE 5 +#define XMODEM_NO_SESSION 6 +#define XMODEM_ABORT 7 +#define XMODEM_TIMEOUT 8 + +/**************************** + * flow control character + ****************************/ +#define SOH 0x01 /* Start of header */ +#define STX 0x02 /* Start of header XModem-1K */ +#define EOT 0x04 /* End of transmission */ +#define ACK 0x06 /* Acknowledge */ +#define NAK 0x15 /* Not acknowledge */ +#define CAN 0x18 /* Cancel */ +#define ESC 0x1b /* User Break */ + +/**************************** + * Xmode paramters + ****************************/ +#define FRAME_SIZE 132 /* X-modem structure */ +#define FRAME_SIZE_1K 1028 /* X-modem structure */ +#define XM_BUFFER_SIZE 1024 /* X-modem buffer */ +#define TIMEOUT 180 /* max timeout */ +#define RETRY_COUNT 20 /* Try times */ +#define xWAITTIME 0x00400000 /* waitiing time */ +#define WAIT_FRAME_TIME (10000*100) /* 10 sec, wait frame timeout */ +#define WAIT_CHAR_TIME (1000*100) /* 1 sec, wait char timeout */ + +/*********************** + * frame structure + ***********************/ +typedef struct +{ + unsigned char soh; + unsigned char recordNo; + unsigned char recordNoInverted; + unsigned char buffer[XM_BUFFER_SIZE]; + unsigned char CRC; +} XMODEM_FRAME; + +typedef struct _XMODEM_COM_PORT_ { + char (*poll) (void); + char (*get)(void); + void (*put)(char c); +}XMODEM_COM_PORT, *PXMODEM_COM_PORT; + +typedef struct _XMODEM_CTRL_ { + u16 xMUsing; + u16 currentFrame; /* current frame number */ + u16 previousFrame; /* previous frame number */ + u16 expected; + s16 rStatus; + s32 rFinish; + u32 total_frame; + u32 rx_len; + char *pXFrameBuf; + u32 (*RxFrameHandler)(char *ptr, u32 frame_num, u32 frame_size); + XMODEM_COM_PORT ComPort; +}XMODEM_CTRL, *PXMODEM_CTRL; + +typedef u32 (*RxFrameHandler_t)(char *ptr, u32 frame_num, u32 frame_size); + +extern s16 xModemStart(XMODEM_CTRL *pXMCtrl, char *FrameBuf, RxFrameHandler_t RxFrameHdl); +extern s16 xModemEnd(XMODEM_CTRL *pXMCtrl); +extern s32 xModemRxBuffer(XMODEM_CTRL *pXMCtrl, s32 MaxSize); + +#endif /* _XMODE_H_ */ + diff --git a/component/common/application/xmodem/xmport_loguart.h b/component/common/application/xmodem/xmport_loguart.h new file mode 100644 index 0000000..27c3abf --- /dev/null +++ b/component/common/application/xmodem/xmport_loguart.h @@ -0,0 +1,25 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _XMPORT_LOGUART_H_ +#define _XMPORT_LOGUART_H_ + +#include "xmodem.h" + +//void xmodem_loguart_init(void); +void xmodem_loguart_init(u32 BaudRate); +void xmodem_loguart_func_hook(XMODEM_COM_PORT *pXComPort); +void xmodem_loguart_deinit(void); +char xmodem_loguart_readable(void); +char xmodem_loguart_writable(void); +char xmodem_loguart_getc(void); +void xmodem_loguart_putc(char c); + +#endif // end of "#define _XMPORT_LOGUART_H_" + diff --git a/component/common/application/xmodem/xmport_uart.h b/component/common/application/xmodem/xmport_uart.h new file mode 100644 index 0000000..2d8134c --- /dev/null +++ b/component/common/application/xmodem/xmport_uart.h @@ -0,0 +1,24 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _XMPORT_UART_H_ +#define _XMPORT_UART_H_ + +#include "xmodem.h" + +void xmodem_uart_init(u8 uart_idx, u8 pin_mux, u32 baud_rate); +void xmodem_uart_func_hook(XMODEM_COM_PORT *pXComPort); +void xmodem_uart_deinit(void); +char xmodem_uart_readable(void); +char xmodem_uart_writable(void); +char xmodem_uart_getc(void); +void xmodem_uart_putc(char c); + +#endif // end of "#define _XMPORT_UART_H_" +