From f8d75f94710a48db5d8306875e28a90ce4fa06f2 Mon Sep 17 00:00:00 2001 From: Tomasz Bursztyka Date: Mon, 9 Oct 2017 13:55:46 +0200 Subject: [PATCH 01/13] ext: Add winc1500 driver from Atmel origin: extracted from Atmel ASF version 3.35.1 Signed-off-by: Tomasz Bursztyka --- ext/hal/atmel/CMakeLists.txt | 2 +- ext/hal/atmel/asf/CMakeLists.txt | 1 + ext/hal/atmel/asf/Kconfig | 3 + ext/hal/atmel/asf/common/CMakeLists.txt | 1 + .../asf/common/components/CMakeLists.txt | 1 + .../asf/common/components/wifi/CMakeLists.txt | 1 + .../components/wifi/winc1500/CMakeLists.txt | 17 + .../common/components/wifi/winc1500/README | 38 + .../wifi/winc1500/bsp/include/nm_bsp.h | 312 ++ .../winc1500/bsp/include/nm_bsp_internal.h | 12 + .../bus_wrapper/include/nm_bus_wrapper.h | 178 + .../wifi/winc1500/common/include/nm_common.h | 153 + .../wifi/winc1500/common/include/nm_debug.h | 95 + .../wifi/winc1500/common/source/nm_common.c | 136 + .../winc1500/driver/include/m2m_ate_mode.h | 732 +++++ .../wifi/winc1500/driver/include/m2m_crypto.h | 272 ++ .../wifi/winc1500/driver/include/m2m_ota.h | 428 +++ .../wifi/winc1500/driver/include/m2m_periph.h | 411 +++ .../wifi/winc1500/driver/include/m2m_types.h | 2383 ++++++++++++++ .../wifi/winc1500/driver/include/m2m_wifi.h | 2882 +++++++++++++++++ .../winc1500/driver/source/m2m_ate_mode.c | 826 +++++ .../wifi/winc1500/driver/source/m2m_crypto.c | 1010 ++++++ .../wifi/winc1500/driver/source/m2m_hif.c | 696 ++++ .../wifi/winc1500/driver/source/m2m_hif.h | 249 ++ .../wifi/winc1500/driver/source/m2m_ota.c | 411 +++ .../wifi/winc1500/driver/source/m2m_periph.c | 161 + .../wifi/winc1500/driver/source/m2m_wifi.c | 1426 ++++++++ .../wifi/winc1500/driver/source/nmasic.c | 664 ++++ .../wifi/winc1500/driver/source/nmasic.h | 215 ++ .../wifi/winc1500/driver/source/nmbus.c | 298 ++ .../wifi/winc1500/driver/source/nmbus.h | 147 + .../wifi/winc1500/driver/source/nmdrv.c | 389 +++ .../wifi/winc1500/driver/source/nmdrv.h | 138 + .../wifi/winc1500/driver/source/nmi2c.c | 269 ++ .../wifi/winc1500/driver/source/nmi2c.h | 104 + .../wifi/winc1500/driver/source/nmspi.c | 1390 ++++++++ .../wifi/winc1500/driver/source/nmspi.h | 132 + .../wifi/winc1500/driver/source/nmuart.c | 536 +++ .../wifi/winc1500/driver/source/nmuart.h | 118 + .../socket/include/m2m_socket_host_if.h | 461 +++ .../wifi/winc1500/socket/include/socket.h | 2061 ++++++++++++ .../wifi/winc1500/socket/source/socket.c | 1309 ++++++++ .../winc1500/socket/source/socket_internal.h | 68 + .../winc1500/spi_flash/include/spi_flash.h | 222 ++ .../spi_flash/include/spi_flash_map.h | 245 ++ .../winc1500/spi_flash/source/spi_flash.c | 754 +++++ 46 files changed, 22356 insertions(+), 1 deletion(-) create mode 100644 ext/hal/atmel/asf/common/CMakeLists.txt create mode 100644 ext/hal/atmel/asf/common/components/CMakeLists.txt create mode 100644 ext/hal/atmel/asf/common/components/wifi/CMakeLists.txt create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/CMakeLists.txt create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/README create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/bsp/include/nm_bsp.h create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/bsp/include/nm_bsp_internal.h create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/bus_wrapper/include/nm_bus_wrapper.h create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/common/include/nm_common.h create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/common/include/nm_debug.h create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/common/source/nm_common.c create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/driver/include/m2m_ate_mode.h create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/driver/include/m2m_crypto.h create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/driver/include/m2m_ota.h create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/driver/include/m2m_periph.h create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/driver/include/m2m_types.h create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/driver/include/m2m_wifi.h create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/m2m_ate_mode.c create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/m2m_crypto.c create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/m2m_hif.c create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/m2m_hif.h create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/m2m_ota.c create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/m2m_periph.c create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/m2m_wifi.c create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmasic.c create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmasic.h create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmbus.c create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmbus.h create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmdrv.c create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmdrv.h create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmi2c.c create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmi2c.h create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmspi.c create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmspi.h create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmuart.c create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmuart.h create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/socket/include/m2m_socket_host_if.h create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/socket/include/socket.h create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/socket/source/socket.c create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/socket/source/socket_internal.h create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/spi_flash/include/spi_flash.h create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/spi_flash/include/spi_flash_map.h create mode 100644 ext/hal/atmel/asf/common/components/wifi/winc1500/spi_flash/source/spi_flash.c diff --git a/ext/hal/atmel/CMakeLists.txt b/ext/hal/atmel/CMakeLists.txt index 82945cd56474a..17d021c6ce44d 100644 --- a/ext/hal/atmel/CMakeLists.txt +++ b/ext/hal/atmel/CMakeLists.txt @@ -1 +1 @@ -add_subdirectory_if_kconfig(asf) +add_subdirectory(asf) diff --git a/ext/hal/atmel/asf/CMakeLists.txt b/ext/hal/atmel/asf/CMakeLists.txt index cf3a1a481ae70..16aa0af0f9424 100644 --- a/ext/hal/atmel/asf/CMakeLists.txt +++ b/ext/hal/atmel/asf/CMakeLists.txt @@ -1,2 +1,3 @@ +add_subdirectory(common) add_subdirectory_ifdef(CONFIG_SOC_FAMILY_SAM sam) add_subdirectory_ifdef(CONFIG_SOC_FAMILY_SAM0 sam0) diff --git a/ext/hal/atmel/asf/Kconfig b/ext/hal/atmel/asf/Kconfig index bd17aa8a0e7d8..7da2e3bf42eeb 100644 --- a/ext/hal/atmel/asf/Kconfig +++ b/ext/hal/atmel/asf/Kconfig @@ -8,3 +8,6 @@ config ASF bool select HAS_CMSIS depends on SOC_FAMILY_SAM || SOC_FAMILY_SAM0 + +config ATMEL_WINC1500 + bool diff --git a/ext/hal/atmel/asf/common/CMakeLists.txt b/ext/hal/atmel/asf/common/CMakeLists.txt new file mode 100644 index 0000000000000..3c357135a2122 --- /dev/null +++ b/ext/hal/atmel/asf/common/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(components) diff --git a/ext/hal/atmel/asf/common/components/CMakeLists.txt b/ext/hal/atmel/asf/common/components/CMakeLists.txt new file mode 100644 index 0000000000000..620242c908925 --- /dev/null +++ b/ext/hal/atmel/asf/common/components/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(wifi) diff --git a/ext/hal/atmel/asf/common/components/wifi/CMakeLists.txt b/ext/hal/atmel/asf/common/components/wifi/CMakeLists.txt new file mode 100644 index 0000000000000..3b066c6893639 --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory_ifdef(CONFIG_ATMEL_WINC1500 winc1500) diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/CMakeLists.txt b/ext/hal/atmel/asf/common/components/wifi/winc1500/CMakeLists.txt new file mode 100644 index 0000000000000..90116c63250f2 --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/CMakeLists.txt @@ -0,0 +1,17 @@ +zephyr_include_directories(./) + +zephyr_sources( + driver/source/m2m_ate_mode.c + driver/source/m2m_crypto.c + driver/source/m2m_hif.c + driver/source/m2m_ota.c + driver/source/m2m_periph.c + driver/source/m2m_wifi.c + driver/source/nmasic.c + driver/source/nmbus.c + driver/source/nmdrv.c + driver/source/nmspi.c + socket/source/socket.c + common/source/nm_common.c + spi_flash/source/spi_flash.c + ) diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/README b/ext/hal/atmel/asf/common/components/wifi/winc1500/README new file mode 100644 index 0000000000000..c5c1e126aa049 --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/README @@ -0,0 +1,38 @@ +Atmel WINC1500 driver in Zephyr is an extraction of the Atmel ASF library. +The original upstream code can be found at: + +http://asf.atmel.com/docs/latest/download.html + +At revision 3.35.1 + +Any changes to the local version should include Zephyr's TinyCrypt +maintainer in the review. That can be found via the git history. + +The following is the license information for this code: + +Copyright (c) 2016-2017 Atmel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. The name of Atmel may not be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE +EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/bsp/include/nm_bsp.h b/ext/hal/atmel/asf/common/components/wifi/winc1500/bsp/include/nm_bsp.h new file mode 100644 index 0000000000000..a16ca073ad451 --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/bsp/include/nm_bsp.h @@ -0,0 +1,312 @@ +/** + * + * \file + * + * \brief WINC BSP API Declarations. + * + * Copyright (c) 2016-2017 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + +/** \defgroup nm_bsp BSP + */ +/**@defgroup BSPDefine Defines + * @ingroup nm_bsp + * @{ + */ +#ifndef _NM_BSP_H_ +#define _NM_BSP_H_ + +#define NMI_API +/*!< +* Attribute used to define memory section to map Functions in host memory. +*/ +#define CONST const + +/*!< +* Used for code portability. +*/ + +#ifndef NULL +#define NULL ((void*)0) +#endif +/*!< +* Void Pointer to '0' in case of NULL is not defined. +*/ + + +#define BSP_MIN(x,y) ((x)>(y)?(y):(x)) +/*!< +* Computes the minimum of \b x and \b y. +*/ + + //@} + +/**@defgroup DataT DataTypes + * @ingroup nm_bsp + * @{ + */ + +/*! + * @typedef void (*tpfNmBspIsr) (void); + * @brief Pointer to function.\n + * Used as a data type of ISR function registered by \ref nm_bsp_register_isr + * @return None + */ +typedef void (*tpfNmBspIsr)(void); + /*! + * @ingroup DataTypes + * @typedef unsigned char uint8; + * @brief Range of values between 0 to 255 + */ +typedef unsigned char uint8; + + /*! + * @ingroup DataTypes + * @typedef unsigned short uint16; + * @brief Range of values between 0 to 65535 + */ +typedef unsigned short uint16; + + /*! + * @ingroup Data Types + * @typedef unsigned long uint32; + * @brief Range of values between 0 to 4294967295 + */ +typedef unsigned long uint32; + /*! + * @ingroup Data Types + * @typedef signed char sint8; + * @brief Range of values between -128 to 127 + */ +typedef signed char sint8; + + /*! + * @ingroup DataTypes + * @typedef signed short sint16; + * @brief Range of values between -32768 to 32767 + */ +typedef signed short sint16; + + /*! + * @ingroup DataTypes + * @typedef signed long sint32; + * @brief Range of values between -2147483648 to 2147483647 + */ + +typedef signed long sint32; + //@} + +#ifndef CORTUS_APP + + +#ifdef __cplusplus +extern "C"{ +#endif + +/** \defgroup BSPAPI Function + * @ingroup nm_bsp + */ + + +/** @defgroup NmBspInitFn nm_bsp_init + * @ingroup BSPAPI + * + * Initialization for BSP (Board Support Package) such as Reset and Chip Enable Pins for WINC, delays, + * register ISR, enable/disable IRQ for WINC, ...etc. You must use this function in the head of your application to + * enable WINC and Host Driver to communicate with each other. + */ + /**@{*/ +/*! + * @fn sint8 nm_bsp_init(void); + * @brief This function is used to initialize the Board Support Package (BSP) in order to prepare the WINC + * before it start working. + * + * The nm_bsp_init function is the first function that should be called at the beginning of + * every application to initialize the BSP and the WINC board. Otherwise, the rest of the BSP function + * calls will return with failure. This function should also be called after the WINC has been switched off with + * a successful call to "nm_bsp_deinit" in order to reinitialize the BSP before the user can use any of the WINC API + * functions again. After the function initialize the WINC. Hard reset must be applied to start the WINC board. + * @note Implementation of this function is host dependent. + * @warning inappropriate use of this function will lead to unavailability of host-chip communication.\n + * + * @see nm_bsp_deinit, nm_bsp_reset + * @return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. + + */ +sint8 nm_bsp_init(void); + /**@}*/ + + + /** @defgroup NmBspDeinitFn nm_bsp_deinit + * @ingroup BSPAPI + * De-initialization for BSP ((Board Support Package)). This function should be called only after + * a successful call to nm_bsp_init. + */ + /**@{*/ +/*! + * @fn sint8 nm_bsp_deinit(void); + * @pre The BSP should be initialized through \ref nm_bsp_init first. + * @brief This function is used to de-initialize the BSP and turn off the WINC board. + * + * The nm_bsp_deinit is the last function that should be called after the application has finished and before the WINC is switched + * off. The function call turns off the WINC board by setting CHIP_EN and RESET_N signals low.Every function call of "nm_bsp_init" should + * be matched with a call to nm_bsp_deinit. Failure to do so may result in the WINC consuming higher power than expected. + * @note Implementation of this function is host dependent. + * @warning misuse may lead to unknown behavior in case of soft reset.\n + * @see nm_bsp_init + * @return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. + + */ +sint8 nm_bsp_deinit(void); + /**@}*/ + + +/** @defgroup NmBspResetFn nm_bsp_reset +* @ingroup BSPAPI +* Resetting WINC1500 SoC by setting CHIP_EN and RESET_N signals low, then after specific delay the function will put CHIP_EN high then RESET_N high, +* for the timing between signals please review the WINC data-sheet +*/ +/**@{*/ + /*! + * @fn void nm_bsp_reset(void); + * @param [in] None + * @brief Applies a hardware reset to the WINC board. + * The "nm_bsp_reset" is used to apply a hard reset to the WINC board by setting CHIP_EN and RESET_N signals low, then after specific delay + * the function will put CHIP_EN high then RESET_N high, for the detailed timing between signals please review the WINC data-sheet. After a + * successful call, the WINC board firmware will kick off to load and kick off the WINC firmware. This function should be called to reset the + * WINC firmware after the BSP is initialized and before the start of any communication with WINC board. Calling this function at any other time + * will result in losing the state and connections saved in the WINC board and starting again from the initial state. The host driver will need + * to be de-initialized before calling nm_bsp_reset and initialized again after it using the " m2m_wifi_(de)init". + * @pre Initialize \ref nm_bsp_init first + * @note Implementation of this function is host dependent and called by HIF layer. + * @warning Calling this function will drop any connection and internal state saved on the WINC firmware. + * @see nm_bsp_init, m2m_wifi_init, m2m_wifi_deinit + * @return None + + */ +void nm_bsp_reset(void); + /**@}*/ + + +/** @defgroup NmBspSleepFn nm_bsp_sleep +* @ingroup BSPAPI +* Sleep in units of milliseconds.\n +* This function used by HIF Layer according to different situations. +*/ +/**@{*/ +/*! + * @fn void nm_bsp_sleep(uint32); + * @brief Used to put the host to sleep for the specified duration. + * Forcing the host to sleep for extended period may lead to host not being able to respond to WINC board events.It's important to + * be considerate while choosing the sleep period. + * @param [in] u32TimeMsec + * Time unit in milliseconds + * @pre Initialize \ref nm_bsp_init first + * @warning Maximum value must nor exceed 4294967295 milliseconds which is equal to 4294967.295 seconds.\n + * @note Implementation of this function is host dependent. + * @see nm_bsp_init + * @return None + */ +void nm_bsp_sleep(uint32 u32TimeMsec); +/**@}*/ + + +/** @defgroup NmBspRegisterFn nm_bsp_register_isr +* @ingroup BSPAPI +* Register ISR (Interrupt Service Routine) in the initialization of HIF (Host Interface) Layer. +* When the interrupt trigger the BSP layer should call the pfisr function once inside the interrupt. +*/ +/**@{*/ +/*! + * @fn void nm_bsp_register_isr(tpfNmBspIsr); + * @param [in] tpfNmBspIsr pfIsr + * Pointer to ISR handler in HIF + * @brief Register the host interface interrupt service routine. + * WINC board utilize SPI interface to communicate with the host. This function register the SPI interrupt the notify + * the host whenever there is an outstanding message from the WINC board. The function should be called during the initialization + * of the host interface. It an internal driver function and shouldn't be called by the application. + * @warning Make sure that ISR for IRQ pin for WINC is disabled by default in your implementation. + * @note Implementation of this function is host dependent and called by HIF layer. + * @see tpfNmBspIsr + * @return None + + */ +void nm_bsp_register_isr(tpfNmBspIsr pfIsr); +/**@}*/ + + +/** @defgroup NmBspInterruptCtrl nm_bsp_interrupt_ctrl +* @ingroup BSPAPI +* Synchronous enable/disable interrupts function +*/ +/**@{*/ +/*! + * @fn void nm_bsp_interrupt_ctrl(uint8); + * @pre The interrupt must be registered using nm_bsp_register_isr first. + * @brief Enable/Disable interrupts + * This function can be used to enable/disable the WINC to host interrupt as the depending on how the driver is implemented. + * It an internal driver function and shouldn't be called by the application. + * @param [in] u8Enable + * '0' disable interrupts. '1' enable interrupts + * @see tpfNmBspIsr, nm_bsp_register_isr + * @note Implementation of this function is host dependent and called by HIF layer. + * @return None + + */ +void nm_bsp_interrupt_ctrl(uint8 u8Enable); + /**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif + +#ifdef _NM_BSP_BIG_END +#define NM_BSP_B_L_32(x) \ +((((x) & 0x000000FF) << 24) + \ +(((x) & 0x0000FF00) << 8) + \ +(((x) & 0x00FF0000) >> 8) + \ +(((x) & 0xFF000000) >> 24)) +#define NM_BSP_B_L_16(x) \ +((((x) & 0x00FF) << 8) + \ +(((x) & 0xFF00) >> 8)) +#else +#define NM_BSP_B_L_32(x) (x) +#define NM_BSP_B_L_16(x) (x) +#endif + + +#endif /*_NM_BSP_H_*/ diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/bsp/include/nm_bsp_internal.h b/ext/hal/atmel/asf/common/components/wifi/winc1500/bsp/include/nm_bsp_internal.h new file mode 100644 index 0000000000000..2608731069734 --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/bsp/include/nm_bsp_internal.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2016 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _NM_BSP_INTERNAL_H_ +#define _NM_BSP_INTERNAL_H_ + +/* dummy nm_bsp_internal.h to make nm_debug.c happy */ + +#endif //_NM_BSP_INTERNAL_H_ diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/bus_wrapper/include/nm_bus_wrapper.h b/ext/hal/atmel/asf/common/components/wifi/winc1500/bus_wrapper/include/nm_bus_wrapper.h new file mode 100644 index 0000000000000..98a1a120e6c9d --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/bus_wrapper/include/nm_bus_wrapper.h @@ -0,0 +1,178 @@ +/** + * + * \file + * + * \brief This module contains NMC1000 bus wrapper APIs declarations. + * + * Copyright (c) 2016-2017 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + +#ifndef _NM_BUS_WRAPPER_H_ +#define _NM_BUS_WRAPPER_H_ + +#include "common/include/nm_common.h" + +/** + BUS Type +**/ +#define NM_BUS_TYPE_I2C ((uint8)0) +#define NM_BUS_TYPE_SPI ((uint8)1) +#define NM_BUS_TYPE_UART ((uint8)2) +/** + IOCTL commands +**/ +#define NM_BUS_IOCTL_R ((uint8)0) /*!< Read only ==> I2C/UART. Parameter:tstrNmI2cDefault/tstrNmUartDefault */ +#define NM_BUS_IOCTL_W ((uint8)1) /*!< Write only ==> I2C/UART. Parameter type tstrNmI2cDefault/tstrNmUartDefault*/ +#define NM_BUS_IOCTL_W_SPECIAL ((uint8)2) /*!< Write two buffers within the same transaction + (same start/stop conditions) ==> I2C only. Parameter:tstrNmI2cSpecial */ +#define NM_BUS_IOCTL_RW ((uint8)3) /*!< Read/Write at the same time ==> SPI only. Parameter:tstrNmSpiRw */ + +#define NM_BUS_IOCTL_WR_RESTART ((uint8)4) /*!< Write buffer then made restart condition then read ==> I2C only. parameter:tstrNmI2cSpecial */ +/** +* @struct tstrNmBusCapabilities +* @brief Structure holding bus capabilities information +* @sa NM_BUS_TYPE_I2C, NM_BUS_TYPE_SPI +*/ +typedef struct +{ + uint16 u16MaxTrxSz; /*!< Maximum transfer size. Must be >= 16 bytes*/ +} tstrNmBusCapabilities; + +/** +* @struct tstrNmI2cDefault +* @brief Structure holding I2C default operation parameters +* @sa NM_BUS_IOCTL_R, NM_BUS_IOCTL_W +*/ +typedef struct +{ + uint8 u8SlaveAdr; + uint8 *pu8Buf; /*!< Operation buffer */ + uint16 u16Sz; /*!< Operation size */ +} tstrNmI2cDefault; + +/** +* @struct tstrNmI2cSpecial +* @brief Structure holding I2C special operation parameters +* @sa NM_BUS_IOCTL_W_SPECIAL +*/ +typedef struct +{ + uint8 u8SlaveAdr; + uint8 *pu8Buf1; /*!< pointer to the 1st buffer */ + uint8 *pu8Buf2; /*!< pointer to the 2nd buffer */ + uint16 u16Sz1; /*!< 1st buffer size */ + uint16 u16Sz2; /*!< 2nd buffer size */ +} tstrNmI2cSpecial; + +/** +* @struct tstrNmSpiRw +* @brief Structure holding SPI R/W parameters +* @sa NM_BUS_IOCTL_RW +*/ +typedef struct +{ + uint8 *pu8InBuf; /*!< pointer to input buffer. + Can be set to null and in this case zeros should be sent at MOSI */ + uint8 *pu8OutBuf; /*!< pointer to output buffer. + Can be set to null and in this case data from MISO can be ignored */ + uint16 u16Sz; /*!< Transfere size */ +} tstrNmSpiRw; + + +/** +* @struct tstrNmUartDefault +* @brief Structure holding UART default operation parameters +* @sa NM_BUS_IOCTL_R, NM_BUS_IOCTL_W +*/ +typedef struct +{ + uint8 *pu8Buf; /*!< Operation buffer */ + uint16 u16Sz; /*!< Operation size */ +} tstrNmUartDefault; +/*!< Bus capabilities. This structure must be declared at platform specific bus wrapper */ +extern tstrNmBusCapabilities egstrNmBusCapabilities; + + +#ifdef __cplusplus + extern "C" { + #endif +/** +* @fn nm_bus_init +* @brief Initialize the bus wrapper +* @return ZERO in case of success and M2M_ERR_BUS_FAIL in case of failure +*/ +sint8 nm_bus_init(void *); + +/** +* @fn nm_bus_ioctl +* @brief send/receive from the bus +* @param [in] u8Cmd +* IOCTL command for the operation +* @param [in] pvParameter +* Arbitrary parameter depending on IOCTL +* @return ZERO in case of success and M2M_ERR_BUS_FAIL in case of failure +* @note For SPI only, it's important to be able to send/receive at the same time +*/ +sint8 nm_bus_ioctl(uint8 u8Cmd, void* pvParameter); + +/** +* @fn nm_bus_deinit +* @brief De-initialize the bus wrapper +* @return ZERO in case of success and M2M_ERR_BUS_FAIL in case of failure +*/ +sint8 nm_bus_deinit(void); + +/* +* @fn nm_bus_reinit +* @brief re-initialize the bus wrapper +* @param [in] void *config +* re-init configuration data +* @return ZERO in case of success and M2M_ERR_BUS_FAIL in case of failure +*/ +sint8 nm_bus_reinit(void *); +/* +* @fn nm_bus_get_chip_type +* @brief get chip type +* @return ZERO in case of success and M2M_ERR_BUS_FAIL in case of failure +*/ +#ifdef CONF_WINC_USE_UART +uint8 nm_bus_get_chip_type(void); +sint8 nm_bus_break(void); +#endif +#ifdef __cplusplus + } + #endif + +#endif /*_NM_BUS_WRAPPER_H_*/ diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/common/include/nm_common.h b/ext/hal/atmel/asf/common/components/wifi/winc1500/common/include/nm_common.h new file mode 100644 index 0000000000000..d66fbdb858386 --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/common/include/nm_common.h @@ -0,0 +1,153 @@ +/** + * + * \file + * + * \brief WINC Driver Common API Declarations. + * + * Copyright (c) 2016-2017 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + +#ifndef _NM_COMMON_H_ +#define _NM_COMMON_H_ + +#include "bsp/include/nm_bsp.h" +#include "common/include/nm_debug.h" + +/**@defgroup CommonDefines CommonDefines + * @ingroup WlanDefines + */ +/**@{*/ +#define M2M_TIME_OUT_DELAY 10000 + +/*states*/ +#define M2M_SUCCESS ((sint8)0) +#define M2M_ERR_SEND ((sint8)-1) +#define M2M_ERR_RCV ((sint8)-2) +#define M2M_ERR_MEM_ALLOC ((sint8)-3) +#define M2M_ERR_TIME_OUT ((sint8)-4) +#define M2M_ERR_INIT ((sint8)-5) +#define M2M_ERR_BUS_FAIL ((sint8)-6) +#define M2M_NOT_YET ((sint8)-7) +#define M2M_ERR_FIRMWARE ((sint8)-8) +#define M2M_SPI_FAIL ((sint8)-9) +#define M2M_ERR_FIRMWARE_bURN ((sint8)-10) +#define M2M_ACK ((sint8)-11) +#define M2M_ERR_FAIL ((sint8)-12) +#define M2M_ERR_FW_VER_MISMATCH ((sint8)-13) +#define M2M_ERR_SCAN_IN_PROGRESS ((sint8)-14) +#define M2M_ERR_INVALID_ARG ((sint8)-15) +#define M2M_ERR_INVALID ((sint8)-16) + +/*i2c MAASTER ERR*/ +#define I2C_ERR_LARGE_ADDRESS 0xE1UL /*the address exceed the max addressing mode in i2c flash*/ +#define I2C_ERR_TX_ABRT 0xE2UL /*NO ACK from slave*/ +#define I2C_ERR_OVER_SIZE 0xE3UL /**/ +#define ERR_PREFIX_NMIS 0xE4UL /*wrong first four byte in flash NMIS*/ +#define ERR_FIRMEWARE_EXCEED_SIZE 0xE5UL /*Total size of firmware exceed the max size 256k*/ +/**/ +#define PROGRAM_START 0x26961735UL +#define BOOT_SUCCESS 0x10add09eUL +#define BOOT_START 0x12345678UL + + +#define NBIT31 (0x80000000) +#define NBIT30 (0x40000000) +#define NBIT29 (0x20000000) +#define NBIT28 (0x10000000) +#define NBIT27 (0x08000000) +#define NBIT26 (0x04000000) +#define NBIT25 (0x02000000) +#define NBIT24 (0x01000000) +#define NBIT23 (0x00800000) +#define NBIT22 (0x00400000) +#define NBIT21 (0x00200000) +#define NBIT20 (0x00100000) +#define NBIT19 (0x00080000) +#define NBIT18 (0x00040000) +#define NBIT17 (0x00020000) +#define NBIT16 (0x00010000) +#define NBIT15 (0x00008000) +#define NBIT14 (0x00004000) +#define NBIT13 (0x00002000) +#define NBIT12 (0x00001000) +#define NBIT11 (0x00000800) +#define NBIT10 (0x00000400) +#define NBIT9 (0x00000200) +#define NBIT8 (0x00000100) +#define NBIT7 (0x00000080) +#define NBIT6 (0x00000040) +#define NBIT5 (0x00000020) +#define NBIT4 (0x00000010) +#define NBIT3 (0x00000008) +#define NBIT2 (0x00000004) +#define NBIT1 (0x00000002) +#define NBIT0 (0x00000001) + +#define M2M_MAX(A,B) ((A) > (B) ? (A) : (B)) +#define M2M_SEL(x,m1,m2,m3) ((x>1)?((x>2)?(m3):(m2)):(m1)) +#define WORD_ALIGN(val) (((val) & 0x03) ? ((val) + 4 - ((val) & 0x03)) : (val)) + + + +#define DATA_PKT_OFFSET 4 + +#ifndef BIG_ENDIAN +#define BYTE_0(word) ((uint8)(((word) >> 0 ) & 0x000000FFUL)) +#define BYTE_1(word) ((uint8)(((word) >> 8 ) & 0x000000FFUL)) +#define BYTE_2(word) ((uint8)(((word) >> 16) & 0x000000FFUL)) +#define BYTE_3(word) ((uint8)(((word) >> 24) & 0x000000FFUL)) +#else +#define BYTE_0(word) ((uint8)(((word) >> 24) & 0x000000FFUL)) +#define BYTE_1(word) ((uint8)(((word) >> 16) & 0x000000FFUL)) +#define BYTE_2(word) ((uint8)(((word) >> 8 ) & 0x000000FFUL)) +#define BYTE_3(word) ((uint8)(((word) >> 0 ) & 0x000000FFUL)) +#endif + +/**@}*/ +#ifdef __cplusplus + extern "C" { + #endif +NMI_API void m2m_memcpy(uint8* pDst,uint8* pSrc,uint32 sz); +NMI_API void m2m_memset(uint8* pBuf,uint8 val,uint32 sz); +NMI_API uint16 m2m_strlen(uint8 * pcStr); +NMI_API sint8 m2m_memcmp(uint8 *pu8Buff1,uint8 *pu8Buff2 ,uint32 u32Size); +NMI_API uint8 m2m_strncmp(uint8 *pcS1, uint8 *pcS2, uint16 u16Len); +NMI_API uint8 * m2m_strstr(uint8 *pcIn, uint8 *pcStr); +NMI_API uint8 m2m_checksum(uint8* buf, int sz); + +#ifdef __cplusplus +} + #endif +#endif /*_NM_COMMON_H_*/ diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/common/include/nm_debug.h b/ext/hal/atmel/asf/common/components/wifi/winc1500/common/include/nm_debug.h new file mode 100644 index 0000000000000..a710f6ce295ca --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/common/include/nm_debug.h @@ -0,0 +1,95 @@ +/** + * + * \file + * + * \brief This module contains debug APIs declarations. + * + * Copyright (c) 2016-2017 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + +#ifndef _NM_DEBUG_H_ +#define _NM_DEBUG_H_ + +#include "bsp/include/nm_bsp.h" +#include "bsp/include/nm_bsp_internal.h" + +/**@defgroup DebugDefines DebugDefines + * @ingroup WlanDefines + */ +/**@{*/ + + +#define M2M_LOG_NONE 0 +#define M2M_LOG_ERROR 1 +#define M2M_LOG_INFO 2 +#define M2M_LOG_REQ 3 +#define M2M_LOG_DBG 4 + +#if (defined __APS3_CORTUS__) +#define M2M_LOG_LEVEL M2M_LOG_INFO +#else +#define M2M_LOG_LEVEL M2M_LOG_REQ +#endif + + +#define M2M_ERR(...) +#define M2M_INFO(...) +#define M2M_REQ(...) +#define M2M_DBG(...) +#define M2M_PRINT(...) + +#if (CONF_WINC_DEBUG == 1) +#undef M2M_PRINT +#define M2M_PRINT(...) do{CONF_WINC_PRINTF(__VA_ARGS__);CONF_WINC_PRINTF("\r");}while(0) +#if (M2M_LOG_LEVEL >= M2M_LOG_ERROR) +#undef M2M_ERR +#define M2M_ERR(...) do{CONF_WINC_PRINTF("(APP)(ERR)[%s][%d]",__FUNCTION__,__LINE__); CONF_WINC_PRINTF(__VA_ARGS__);CONF_WINC_PRINTF("\r");}while(0) +#if (M2M_LOG_LEVEL >= M2M_LOG_INFO) +#undef M2M_INFO +#define M2M_INFO(...) do{CONF_WINC_PRINTF("(APP)(INFO)"); CONF_WINC_PRINTF(__VA_ARGS__);CONF_WINC_PRINTF("\r");}while(0) +#if (M2M_LOG_LEVEL >= M2M_LOG_REQ) +#undef M2M_REQ +#define M2M_REQ(...) do{CONF_WINC_PRINTF("(APP)(R)"); CONF_WINC_PRINTF(__VA_ARGS__);CONF_WINC_PRINTF("\r");}while(0) +#if (M2M_LOG_LEVEL >= M2M_LOG_DBG) +#undef M2M_DBG +#define M2M_DBG(...) do{CONF_WINC_PRINTF("(APP)(DBG)[%s][%d]",__FUNCTION__,__LINE__); CONF_WINC_PRINTF(__VA_ARGS__);CONF_WINC_PRINTF("\r");}while(0) +#endif /*M2M_LOG_DBG*/ +#endif /*M2M_LOG_REQ*/ +#endif /*M2M_LOG_INFO*/ +#endif /*M2M_LOG_ERROR*/ +#endif /*CONF_WINC_DEBUG */ + +/**@}*/ +#endif /* _NM_DEBUG_H_ */ diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/common/source/nm_common.c b/ext/hal/atmel/asf/common/components/wifi/winc1500/common/source/nm_common.c new file mode 100644 index 0000000000000..8b3c941c50380 --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/common/source/nm_common.c @@ -0,0 +1,136 @@ +/** + * + * \file + * + * \brief This module contains common APIs declarations. + * + * Copyright (c) 2016 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ +#include "common/include/nm_common.h" + +void m2m_memcpy(uint8* pDst,uint8* pSrc,uint32 sz) +{ + if(sz == 0) return; + do + { + *pDst = *pSrc; + pDst++; + pSrc++; + }while(--sz); +} +uint8 m2m_checksum(uint8* buf, int sz) +{ + uint8 cs = 0; + while(--sz) + { + cs ^= *buf; + buf++; + } + + return cs; +} + +void m2m_memset(uint8* pBuf,uint8 val,uint32 sz) +{ + if(sz == 0) return; + do + { + *pBuf = val; + pBuf++; + }while(--sz); +} + +uint16 m2m_strlen(uint8 * pcStr) +{ + uint16 u16StrLen = 0; + while(*pcStr) + { + u16StrLen ++; + pcStr++; + } + return u16StrLen; +} + +uint8 m2m_strncmp(uint8 *pcS1, uint8 *pcS2, uint16 u16Len) +{ + for ( ; u16Len > 0; pcS1++, pcS2++, --u16Len) + if (*pcS1 != *pcS2) + return ((*(uint8 *)pcS1 < *(uint8 *)pcS2) ? -1 : +1); + else if (*pcS1 == '\0') + return 0; + return 0; +} + +/* Finds the occurance of pcStr in pcIn. +If pcStr is part of pcIn it returns a valid pointer to the start of pcStr within pcIn. +Otherwise a NULL Pointer is returned. +*/ +uint8 * m2m_strstr(uint8 *pcIn, uint8 *pcStr) +{ + uint8 u8c; + uint16 u16StrLen; + + u8c = *pcStr++; + if (!u8c) + return (uint8 *) pcIn; // Trivial empty string case + + u16StrLen = m2m_strlen(pcStr); + do { + uint8 u8Sc; + + do { + u8Sc = *pcIn++; + if (!u8Sc) + return (uint8 *) 0; + } while (u8Sc != u8c); + } while (m2m_strncmp(pcIn, pcStr, u16StrLen) != 0); + + return (uint8 *) (pcIn - 1); +} + +sint8 m2m_memcmp(uint8 *pu8Buff1,uint8 *pu8Buff2 ,uint32 u32Size) +{ + uint32 i; + sint8 s8Result = 0; + for(i = 0 ; i < u32Size ; i++) + { + if(pu8Buff1[i] != pu8Buff2[i]) + { + s8Result = 1; + break; + } + } + return s8Result; +} diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/include/m2m_ate_mode.h b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/include/m2m_ate_mode.h new file mode 100644 index 0000000000000..a17d298614fb5 --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/include/m2m_ate_mode.h @@ -0,0 +1,732 @@ +/** + * + * \file + * + * \brief WINC ATE Test Driver Interface. + * + * Copyright (c) 2016-2017 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + +#ifdef _M2M_ATE_FW_ + +#ifndef _M2M_ATE_MODE_H_ +#define _M2M_ATE_MODE_H_ + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +INCLUDES +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ +#include "common/include/nm_common.h" +#include "driver/include/m2m_types.h" + +/** \defgroup m2m_ate ATE +*/ +/**@defgroup ATEDefine Defines + * @ingroup m2m_ate + * @{ + */ +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +MACROS +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ +#define M2M_ATE_MAX_NUM_OF_RATES (20) +/*!< +Maximum number of all rates (b,g and n) + */ +#define M2M_ATE_MAX_FRAME_LENGTH (1024) +/*!< Maximum number of length for each frame + */ +#define M2M_ATE_MIN_FRAME_LENGTH (1) +/*!< Minimum number of length for each frame + */ +#define M2M_ATE_SUCCESS (M2M_SUCCESS) +/*!< No Error and operation has been completed successfully. +*/ +#define M2M_ATE_ERR_VALIDATE (M2M_ERR_FAIL) +/*!< Error in parameters passed to functions. + */ +#define M2M_ATE_ERR_TX_ALREADY_RUNNING (-1) +/*!< Error in starting a transmission test. Another test is already running and its not allowed to start another ATE test. + */ +#define M2M_ATE_ERR_RX_ALREADY_RUNNING (-2) +/*!< Error in starting a reception test. Another test is already running and its not allowed to start another ATE test. + */ +#define M2M_ATE_ERR_UNHANDLED_CASE (-3) +/*!< Invalid case. + */ +#define M2M_ATE_RX_DISABLE_DA 0x0 +/*!< Filter selection for received frames: Disable filtering received frames by the destination address. + */ +#define M2M_ATE_RX_ENABLE_DA 0x1 +/*!< Filter selection for received frames: Enable filtering received frames by the destination address. + */ +#define M2M_ATE_RX_DISABLE_SA 0x0 +/*!< Filter selection for received frames: Disable filtering received frames by the source address. + */ +#define M2M_ATE_RX_ENABLE_SA 0x1 +/*!< Filter selection for received frames: Enable filtering received frames by the source address. + */ +#define M2M_ATE_DISABLE_SELF_MACADDR 0x0 +/*!\n",ret); + while(1); + } + //Initialize the OTA module + m2m_ota_init(OtaUpdateCb,NULL); + //connect to AP that provide connection to the OTA server + m2m_wifi_default_connect(); + + while(1) + { + + //Handle the app state machine plus the WINC event handler + while(m2m_wifi_handle_events(NULL) != M2M_SUCCESS) { + + } + + } +} +@endcode + +*/ +NMI_API sint8 m2m_ota_start_update(uint8 * u8DownloadUrl); + /**@}*/ +/** @defgroup OtaStartUpdatefn m2m_ota_start_update_crt +* @ingroup WLANAPI +* Request OTA start for cortus application image using the downloaded URL, the OTA module will download the OTA image and ensure integrity of the image, +* and update the validity of the image in control structure. Switching to that image requires calling @ref m2m_ota_switch_crt API. +* As a prerequisite @ref m2m_ota_init should be called before using @ref m2m_ota_start_update_crt(). +*/ + /**@{*/ +/*! +@fn \ + NMI_API sint8 m2m_ota_start_update_crt(uint8 * u8DownloadUrl); + +@param [in] u8DownloadUrl + The cortus application image url. +@warning + Calling this API does not guarantee cortus application image update, It depends on the connection with the download server and the validity of the image. + If the API response is failure this may invalidate the roll-back image if it was previously valid, since the WINC does not have any internal memory + except the flash roll-back image location to validate the downloaded image from + +@see + m2m_ota_init + tpfOtaUpdateCb + +@return + The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +*/ +NMI_API sint8 m2m_ota_start_update_crt(uint8 * u8DownloadUrl); + /**@}*/ +/** @defgroup OtaRollbackfn m2m_ota_rollback +* @ingroup WLANAPI + Request OTA Roll-back to the old (other) WINC image, the WINC firmware will check the validation of the Roll-back image + and switch to it if it is valid. + If the API response is success, system restart is required (re-initialize the driver with hardware rest) update the host driver version may + be required if it is did not match the minimum version supported by the WINC firmware. + +*/ + /**@{*/ +/*! +@fn \ + NMI_API sint8 m2m_ota_rollback(void); + +@sa + m2m_ota_init + m2m_ota_start_update + +@return + The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +*/ +NMI_API sint8 m2m_ota_rollback(void); + /**@}*/ +/** @defgroup OtaRollbackfn m2m_ota_rollback_crt +* @ingroup WLANAPI + Request Cortus application OTA Roll-back to the old (other) cortus application image, the WINC firmware will check the validation of the Roll-back image + and switch to it if it is valid. + If the API response is success, system restart is required (re-initialize the driver with hardware rest) update the host driver version may + be required. + +*/ + /**@{*/ +/*! +@fn \ + NMI_API sint8 m2m_ota_rollback_crt(void); + +@sa + m2m_ota_init + m2m_ota_start_update_crt + +@return + The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +*/ +NMI_API sint8 m2m_ota_rollback_crt(void); + /**@}*/ +/** @defgroup OtaAbortfn m2m_ota_abort +* @ingroup WLANAPI + Request abort of current OTA download. + The WINC firmware will terminate the OTA download if one is in progress. + If no download is in progress, the API will respond with failure. +*/ + /**@{*/ +/*! +@fn \ + NMI_API sint8 m2m_ota_abort(void); + +@return + The function returns @ref M2M_SUCCESS for successful operation and a negative value otherwise. +*/ +NMI_API sint8 m2m_ota_abort(void); + /**@}*/ + /**@}*/ +/** @defgroup OtaSwitchFirmware m2m_ota_switch_firmware +* @ingroup WLANAPI +* Switch to the upgraded Firmware, that API will update the control structure working image to the upgraded image + take effect will be on the next system restart +*/ + /**@{*/ +/*! +@fn \ + NMI_API sint8 m2m_ota_switch_firmware(void); + +@warning + It is important to note that if the API succeeds, system restart is required (re-initializing the driver with hardware reset) updating the host driver version may be required + if it does not match the minimum driver version supported by the WINC's firmware. +@sa + m2m_ota_init + m2m_ota_start_update + +@return + The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +*/ +NMI_API sint8 m2m_ota_switch_firmware(void); + /**@}*/ + /**@}*/ +/** @defgroup OtaSwitchFirmware m2m_ota_switch_crt +* @ingroup WLANAPI +* Switch to the upgraded cortus application, that API will update the control structure working image to the upgraded image + take effect will be on the next system restart +*/ + /**@{*/ +/*! +@fn \ + NMI_API sint8 m2m_ota_switch_firmware(void); + +@warning + It is important to note that if the API succeeds, system restart is required (re-initializing the driver with hardware reset) updating the host driver version may be required + if it does not match the minimum driver version supported by the WINC's firmware. +@sa + m2m_ota_init + m2m_ota_start_update_crt + +@return + The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +*/ +NMI_API sint8 m2m_ota_switch_crt(void); +/*! +@fn \ + NMI_API sint8 m2m_ota_get_firmware_version(void); + +@brief + Get the OTA Firmware version. + +@return + The function SHALL return 0 for success and a negative value otherwise. +*/ +NMI_API sint8 m2m_ota_get_firmware_version(tstrM2mRev *pstrRev); + /**@}*/ +NMI_API sint8 m2m_ota_test(void); + +#ifdef __cplusplus +} +#endif +#endif /* __M2M_OTA_H__ */ diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/include/m2m_periph.h b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/include/m2m_periph.h new file mode 100644 index 0000000000000..1012882f0211b --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/include/m2m_periph.h @@ -0,0 +1,411 @@ +/** + * + * \file + * + * \brief WINC Peripherals Application Interface. + * + * Copyright (c) 2016 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + +#ifndef _M2M_PERIPH_H_ +#define _M2M_PERIPH_H_ + + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +INCLUDES +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ + + +#include "common/include/nm_common.h" +#include "driver/include/m2m_types.h" + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +MACROS +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +DATA TYPES +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ + +/*! +@struct \ + tstrPerphInitParam + +@brief + Peripheral module initialization parameters. +*/ +typedef struct { + void * arg; +} tstrPerphInitParam; + + +/*! +@enum \ + tenuGpioNum + +@brief + A list of GPIO numbers configurable through the m2m_periph module. +*/ +typedef enum { + M2M_PERIPH_GPIO3, /*!< GPIO15 pad */ + M2M_PERIPH_GPIO4, /*!< GPIO16 pad */ + M2M_PERIPH_GPIO5, /*!< GPIO18 pad */ + M2M_PERIPH_GPIO6, /*!< GPIO18 pad */ + M2M_PERIPH_GPIO15, /*!< GPIO15 pad */ + M2M_PERIPH_GPIO16, /*!< GPIO16 pad */ + M2M_PERIPH_GPIO18, /*!< GPIO18 pad */ + M2M_PERIPH_GPIO_MAX +} tenuGpioNum; + + +/*! +@enum \ + tenuI2cMasterSclMuxOpt + +@brief + Allowed pin multiplexing options for I2C master SCL signal. +*/ +typedef enum { + M2M_PERIPH_I2C_MASTER_SCL_MUX_OPT_HOST_WAKEUP, /*!< I2C master SCL is avaiable on HOST_WAKEUP. */ + M2M_PERIPH_I2C_MASTER_SCL_MUX_OPT_SD_DAT3, /*!< I2C master SCL is avaiable on SD_DAT3 (GPIO 7). */ + M2M_PERIPH_I2C_MASTER_SCL_MUX_OPT_GPIO13, /*!< I2C master SCL is avaiable on GPIO 13. */ + M2M_PERIPH_I2C_MASTER_SCL_MUX_OPT_GPIO4, /*!< I2C master SCL is avaiable on GPIO 4.*/ + M2M_PERIPH_I2C_MASTER_SCL_MUX_OPT_I2C_SCL, /*!< I2C master SCL is avaiable on I2C slave SCL. */ + M2M_PERIPH_I2C_MASTER_SCL_MUX_OPT_NUM +} tenuI2cMasterSclMuxOpt; + +/*! +@enum \ + tenuI2cMasterSdaMuxOpt + +@brief + Allowed pin multiplexing options for I2C master SDA signal. +*/ +typedef enum { + M2M_PERIPH_I2C_MASTER_SDA_MUX_OPT_RTC_CLK , /*!< I2C master SDA is avaiable on RTC_CLK. */ + M2M_PERIPH_I2C_MASTER_SDA_MUX_OPT_SD_CLK, /*!< I2C master SDA is avaiable on SD_CLK (GPIO 8). */ + M2M_PERIPH_I2C_MASTER_SDA_MUX_OPT_GPIO14, /*!< I2C master SDA is avaiable on GPIO 14. */ + M2M_PERIPH_I2C_MASTER_SDA_MUX_OPT_GPIO6, /*!< I2C master SDA is avaiable on GPIO 6.*/ + M2M_PERIPH_I2C_MASTER_SDA_MUX_OPT_I2C_SDA, /*!< I2C master SDA is avaiable on I2C slave SDA. */ + M2M_PERIPH_I2C_MASTER_SDA_MUX_OPT_NUM +} tenuI2cMasterSdaMuxOpt; + + +/*! +@struct \ + tstrI2cMasterInitParam + +@brief + I2C master configuration parameters. +@sa + tenuI2cMasterSclMuxOpt + tenuI2cMasterSdaMuxOpt +*/ +typedef struct { + uint8 enuSclMuxOpt; /*!< SCL multiplexing option. Allowed value are defined in tenuI2cMasterSclMuxOpt */ + uint8 enuSdaMuxOpt; /*!< SDA multiplexing option. Allowed value are defined in tenuI2cMasterSdaMuxOpt */ + uint8 u8ClkSpeedKHz; /*!< I2C master clock speed in KHz. */ +} tstrI2cMasterInitParam; + +/*! +@enum \ + tenuI2cMasterFlags + +@brief + Bitwise-ORed flags for use in m2m_periph_i2c_master_write and m2m_periph_i2c_master_read +@sa + m2m_periph_i2c_master_write + m2m_periph_i2c_master_read +*/ +typedef enum { + I2C_MASTER_NO_FLAGS = 0x00, + /*!< No flags. */ + I2C_MASTER_NO_STOP = 0x01, + /*!< No stop bit after this transaction. Useful for scattered buffer read/write operations. */ + I2C_MASTER_NO_START = 0x02, + /*!< No start bit at the beginning of this transaction. Useful for scattered buffer read/write operations.*/ +} tenuI2cMasterFlags; + +/*! +@enum \ + tenuPullupMask + +@brief + Bitwise-ORed flags for use in m2m_perph_pullup_ctrl. +@sa + m2m_periph_pullup_ctrl + +*/ +typedef enum { + M2M_PERIPH_PULLUP_DIS_HOST_WAKEUP = (1ul << 0), + M2M_PERIPH_PULLUP_DIS_RTC_CLK = (1ul << 1), + M2M_PERIPH_PULLUP_DIS_IRQN = (1ul << 2), + M2M_PERIPH_PULLUP_DIS_GPIO_3 = (1ul << 3), + M2M_PERIPH_PULLUP_DIS_GPIO_4 = (1ul << 4), + M2M_PERIPH_PULLUP_DIS_GPIO_5 = (1ul << 5), + M2M_PERIPH_PULLUP_DIS_SD_DAT3 = (1ul << 6), + M2M_PERIPH_PULLUP_DIS_SD_DAT2_SPI_RXD = (1ul << 7), + M2M_PERIPH_PULLUP_DIS_SD_DAT1_SPI_SSN = (1ul << 9), + M2M_PERIPH_PULLUP_DIS_SD_CMD_SPI_SCK = (1ul << 10), + M2M_PERIPH_PULLUP_DIS_SD_DAT0_SPI_TXD = (1ul << 11), + M2M_PERIPH_PULLUP_DIS_GPIO_6 = (1ul << 12), + M2M_PERIPH_PULLUP_DIS_SD_CLK = (1ul << 13), + M2M_PERIPH_PULLUP_DIS_I2C_SCL = (1ul << 14), + M2M_PERIPH_PULLUP_DIS_I2C_SDA = (1ul << 15), + M2M_PERIPH_PULLUP_DIS_GPIO_11 = (1ul << 16), + M2M_PERIPH_PULLUP_DIS_GPIO_12 = (1ul << 17), + M2M_PERIPH_PULLUP_DIS_GPIO_13 = (1ul << 18), + M2M_PERIPH_PULLUP_DIS_GPIO_14 = (1ul << 19), + M2M_PERIPH_PULLUP_DIS_GPIO_15 = (1ul << 20), + M2M_PERIPH_PULLUP_DIS_GPIO_16 = (1ul << 21), + M2M_PERIPH_PULLUP_DIS_GPIO_17 = (1ul << 22), + M2M_PERIPH_PULLUP_DIS_GPIO_18 = (1ul << 23), + M2M_PERIPH_PULLUP_DIS_GPIO_19 = (1ul << 24), + M2M_PERIPH_PULLUP_DIS_GPIO_20 = (1ul << 25), + M2M_PERIPH_PULLUP_DIS_GPIO_21 = (1ul << 26), + M2M_PERIPH_PULLUP_DIS_GPIO_22 = (1ul << 27), + M2M_PERIPH_PULLUP_DIS_GPIO_23 = (1ul << 28), + M2M_PERIPH_PULLUP_DIS_GPIO_24 = (1ul << 29), +} tenuPullupMask; + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +FUNCTION PROTOTYPES +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ + + +#ifdef __cplusplus + extern "C" { +#endif + +/*! +@fn \ + NMI_API sint8 m2m_periph_init(tstrPerphInitParam * param); + +@brief + Initialize the NMC1500 peripheral driver module. + +@param [in] param + Peripheral module initialization structure. See members of tstrPerphInitParam. + +@return + The function SHALL return 0 for success and a negative value otherwise. + +@sa + tstrPerphInitParam +*/ +NMI_API sint8 m2m_periph_init(tstrPerphInitParam * param); + +/*! +@fn \ + NMI_API sint8 m2m_periph_gpio_set_dir(uint8 u8GpioNum, uint8 u8GpioDir); + +@brief + Configure a specific NMC1500 pad as a GPIO and sets its direction (input or output). + +@param [in] u8GpioNum + GPIO number. Allowed values are defined in tenuGpioNum. + +@param [in] u8GpioDir + GPIO direction: Zero = input. Non-zero = output. + +@return + The function SHALL return 0 for success and a negative value otherwise. + +@sa + tenuGpioNum +*/ +NMI_API sint8 m2m_periph_gpio_set_dir(uint8 u8GpioNum, uint8 u8GpioDir); + +/*! +@fn \ + NMI_API sint8 m2m_periph_gpio_set_val(uint8 u8GpioNum, uint8 u8GpioVal); + +@brief + Set an NMC1500 GPIO output level high or low. + +@param [in] u8GpioNum + GPIO number. Allowed values are defined in tenuGpioNum. + +@param [in] u8GpioVal + GPIO output value. Zero = low, non-zero = high. + +@return + The function SHALL return 0 for success and a negative value otherwise. + +@sa + tenuGpioNum +*/ +NMI_API sint8 m2m_periph_gpio_set_val(uint8 u8GpioNum, uint8 u8GpioVal); + +/*! +@fn \ + NMI_API sint8 m2m_periph_gpio_get_val(uint8 u8GpioNum, uint8 * pu8GpioVal); + +@brief + Read an NMC1500 GPIO input level. + +@param [in] u8GpioNum + GPIO number. Allowed values are defined in tenuGpioNum. + +@param [out] pu8GpioVal + GPIO input value. Zero = low, non-zero = high. + +@return + The function SHALL return 0 for success and a negative value otherwise. + +@sa + tenuGpioNum +*/ +NMI_API sint8 m2m_periph_gpio_get_val(uint8 u8GpioNum, uint8 * pu8GpioVal); + +/*! +@fn \ + NMI_API sint8 m2m_periph_gpio_pullup_ctrl(uint8 u8GpioNum, uint8 u8PullupEn); + +@brief + Set an NMC1500 GPIO pullup resisitor enable or disable. + +@param [in] u8GpioNum + GPIO number. Allowed values are defined in tenuGpioNum. + +@param [in] u8PullupEn + Zero: pullup disabled. Non-zero: pullup enabled. + +@return + The function SHALL return 0 for success and a negative value otherwise. + +@sa + tenuGpioNum +*/ +NMI_API sint8 m2m_periph_gpio_pullup_ctrl(uint8 u8GpioNum, uint8 u8PullupEn); + +/*! +@fn \ + NMI_API sint8 m2m_periph_i2c_master_init(tstrI2cMasterInitParam * param); + +@brief + Initialize and configure the NMC1500 I2C master peripheral. + +@param [in] param + I2C master initialization structure. See members of tstrI2cMasterInitParam. + +@return + The function SHALL return 0 for success and a negative value otherwise. + +@sa + tstrI2cMasterInitParam +*/ +NMI_API sint8 m2m_periph_i2c_master_init(tstrI2cMasterInitParam * param); + +/*! +@fn \ + NMI_API sint8 m2m_periph_i2c_master_write(uint8 u8SlaveAddr, uint8 * pu8Buf, uint16 u16BufLen, uint8 flags); + +@brief + Write a stream of bytes to the I2C slave device. + +@param [in] u8SlaveAddr + 7-bit I2C slave address. +@param [in] pu8Buf + A pointer to an input buffer which contains a stream of bytes. +@param [in] u16BufLen + Input buffer length in bytes. +@param [in] flags + Write operation bitwise-ORed flags. See tenuI2cMasterFlags. + +@return + The function SHALL return 0 for success and a negative value otherwise. + +@sa + tenuI2cMasterFlags +*/ +NMI_API sint8 m2m_periph_i2c_master_write(uint8 u8SlaveAddr, uint8 * pu8Buf, uint16 u16BufLen, uint8 flags); + + +/*! +@fn \ + NMI_API sint8 m2m_periph_i2c_master_read(uint8 u8SlaveAddr, uint8 * pu8Buf, uint16 u16BufLen, uint16 * pu16ReadLen, uint8 flags); + +@brief + Write a stream of bytes to the I2C slave device. + +@param [in] u8SlaveAddr + 7-bit I2C slave address. +@param [out] pu8Buf + A pointer to an output buffer in which a stream of bytes are received. +@param [in] u16BufLen + Max output buffer length in bytes. +@param [out] pu16ReadLen + Actual number of bytes received. +@param [in] flags + Write operation bitwise-ORed flags. See tenuI2cMasterFlags. + +@return + The function SHALL return 0 for success and a negative value otherwise. + +@sa + tenuI2cMasterFlags +*/ +NMI_API sint8 m2m_periph_i2c_master_read(uint8 u8SlaveAddr, uint8 * pu8Buf, uint16 u16BufLen, uint16 * pu16ReadLen, uint8 flags); + + +/*! +@fn \ + NMI_API sint8 m2m_periph_pullup_ctrl(uint32 pinmask, uint8 enable); + +@brief + Control the programmable pull-up resistor on the chip pads . + + +@param [in] pinmask + Write operation bitwise-ORed mask for which pads to control. Allowed values are defined in tenuPullupMask. + +@param [in] enable + Set to 0 to disable pull-up resistor. Non-zero will enable the pull-up. + +@return + The function SHALL return 0 for success and a negative value otherwise. + +@sa + tenuPullupMask +*/ +NMI_API sint8 m2m_periph_pullup_ctrl(uint32 pinmask, uint8 enable); + +#ifdef __cplusplus +} +#endif + + +#endif /* _M2M_PERIPH_H_ */ \ No newline at end of file diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/include/m2m_types.h b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/include/m2m_types.h new file mode 100644 index 0000000000000..a847f3fd974cf --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/include/m2m_types.h @@ -0,0 +1,2383 @@ +/** + * + * \file + * + * \brief WINC Application Interface Internal Types. + * + * Copyright (c) 2016-2017 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + +#ifndef __M2M_WIFI_TYPES_H__ +#define __M2M_WIFI_TYPES_H__ + + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +INCLUDES +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ + +#ifndef _BOOT_ +#ifndef _FIRMWARE_ +#include "common/include/nm_common.h" +#else +#include "m2m_common.h" +#endif +#endif + + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +MACROS +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ +/**@defgroup WlanDefines Defines + * @ingroup m2m_wifi + */ +/**@{*/ +#define M2M_MAJOR_SHIFT (8) +#define M2M_MINOR_SHIFT (4) +#define M2M_PATCH_SHIFT (0) + +#define M2M_DRV_VERSION_SHIFT (16) +#define M2M_FW_VERSION_SHIFT (0) + +#define M2M_GET_MAJOR(ver_info_hword) ((uint8)((ver_info_hword) >> M2M_MAJOR_SHIFT) & 0xff) +#define M2M_GET_MINOR(ver_info_hword) ((uint8)((ver_info_hword) >> M2M_MINOR_SHIFT) & 0x0f) +#define M2M_GET_PATCH(ver_info_hword) ((uint8)((ver_info_hword) >> M2M_PATCH_SHIFT) & 0x0f) + +#define M2M_GET_FW_VER(ver_info_word) ((uint16) ((ver_info_word) >> M2M_FW_VERSION_SHIFT)) +#define M2M_GET_DRV_VER(ver_info_word) ((uint16) ((ver_info_word) >> M2M_DRV_VERSION_SHIFT)) + +#define M2M_GET_DRV_MAJOR(ver_info_word) M2M_GET_MAJOR(M2M_GET_DRV_VER(ver_info_word)) +#define M2M_GET_DRV_MINOR(ver_info_word) M2M_GET_MINOR(M2M_GET_DRV_VER(ver_info_word)) +#define M2M_GET_DRV_PATCH(ver_info_word) M2M_GET_PATCH(M2M_GET_DRV_VER(ver_info_word)) + +#define M2M_GET_FW_MAJOR(ver_info_word) M2M_GET_MAJOR(M2M_GET_FW_VER(ver_info_word)) +#define M2M_GET_FW_MINOR(ver_info_word) M2M_GET_MINOR(M2M_GET_FW_VER(ver_info_word)) +#define M2M_GET_FW_PATCH(ver_info_word) M2M_GET_PATCH(M2M_GET_FW_VER(ver_info_word)) + +#define M2M_MAKE_VERSION(major, minor, patch) ( \ + ((uint16)((major) & 0xff) << M2M_MAJOR_SHIFT) | \ + ((uint16)((minor) & 0x0f) << M2M_MINOR_SHIFT) | \ + ((uint16)((patch) & 0x0f) << M2M_PATCH_SHIFT)) + +#define M2M_MAKE_VERSION_INFO(fw_major, fw_minor, fw_patch, drv_major, drv_minor, drv_patch) \ + ( \ + ( ((uint32)M2M_MAKE_VERSION((fw_major), (fw_minor), (fw_patch))) << M2M_FW_VERSION_SHIFT) | \ + ( ((uint32)M2M_MAKE_VERSION((drv_major), (drv_minor), (drv_patch))) << M2M_DRV_VERSION_SHIFT)) + +#define REL_19_5_2_VER M2M_MAKE_VERSION_INFO(19,5,2,19,3,0) +#define REL_19_5_1_VER M2M_MAKE_VERSION_INFO(19,5,1,19,3,0) +#define REL_19_5_0_VER M2M_MAKE_VERSION_INFO(19,5,0,19,3,0) +#define REL_19_4_6_VER M2M_MAKE_VERSION_INFO(19,4,6,19,3,0) +#define REL_19_4_5_VER M2M_MAKE_VERSION_INFO(19,4,5,19,3,0) +#define REL_19_4_4_VER M2M_MAKE_VERSION_INFO(19,4,4,19,3,0) +#define REL_19_4_3_VER M2M_MAKE_VERSION_INFO(19,4,3,19,3,0) +#define REL_19_4_2_VER M2M_MAKE_VERSION_INFO(19,4,2,19,3,0) +#define REL_19_4_1_VER M2M_MAKE_VERSION_INFO(19,4,1,19,3,0) +#define REL_19_4_0_VER M2M_MAKE_VERSION_INFO(19,4,0,19,3,0) +#define REL_19_3_1_VER M2M_MAKE_VERSION_INFO(19,3,1,19,3,0) +#define REL_19_3_0_VER M2M_MAKE_VERSION_INFO(19,3,0,19,3,0) +#define REL_19_2_2_VER M2M_MAKE_VERSION_INFO(19,2,2,19,2,0) +#define REL_19_2_1_VER M2M_MAKE_VERSION_INFO(19,2,1,19,2,0) +#define REL_19_2_0_VER M2M_MAKE_VERSION_INFO(19,2,0,19,2,0) +#define REL_19_1_0_VER M2M_MAKE_VERSION_INFO(19,1,0,18,2,0) +#define REL_19_0_0_VER M2M_MAKE_VERSION_INFO(19,0,0,18,1,1) + +/*======*======*======*======* + FIRMWARE VERSION NO INFO + *======*======*======*======*/ + +#define M2M_RELEASE_VERSION_MAJOR_NO (19) +/*!< Firmware Major release version number. +*/ + + +#define M2M_RELEASE_VERSION_MINOR_NO (5) +/*!< Firmware Minor release version number. +*/ + +#define M2M_RELEASE_VERSION_PATCH_NO (2) +/*!< Firmware patch release version number. +*/ + +/*======*======*======*======* + SUPPORTED DRIVER VERSION NO INFO + *======*======*======*======*/ + +#define M2M_MIN_REQ_DRV_VERSION_MAJOR_NO (19) +/*!< Driver Major release version number. +*/ + + +#define M2M_MIN_REQ_DRV_VERSION_MINOR_NO (3) +/*!< Driver Minor release version number. +*/ + +#define M2M_MIN_REQ_DRV_VERSION_PATCH_NO (0) +/*!< Driver patch release version number. +*/ + +#define M2M_MIN_REQ_DRV_SVN_VERSION (0) +/*!< Driver svn version. +*/ + + + +#if !defined(M2M_RELEASE_VERSION_MAJOR_NO) || !defined(M2M_RELEASE_VERSION_MINOR_NO) +#error Undefined version number +#endif + +#define M2M_BUFFER_MAX_SIZE (1600UL - 4) +/*!< Maximum size for the shared packet buffer. + */ + + +#define M2M_MAC_ADDRES_LEN 6 +/*!< The size fo 802 MAC address. + */ + +#define M2M_ETHERNET_HDR_OFFSET 34 +/*!< The offset of the Ethernet header within the WLAN Tx Buffer. + */ + + +#define M2M_ETHERNET_HDR_LEN 14 +/*!< Length of the Etherenet header in bytes. +*/ + + +#define M2M_MAX_SSID_LEN 33 +/*!< Maximum size for the Wi-Fi SSID including the NULL termination. + */ + + +#define M2M_MAX_PSK_LEN 65 +/*!< Maximum size for the WPA PSK including the NULL termination. + */ + +#define M2M_MIN_PSK_LEN 9 +/*!< Maximum size for the WPA PSK including the NULL termination. + */ + +#define M2M_DEVICE_NAME_MAX 48 +/*!< Maximum Size for the device name including the NULL termination. + */ + + +#define M2M_LISTEN_INTERVAL 1 +/*!< The STA uses the Listen Interval parameter to indicate to the AP how + many beacon intervals it shall sleep before it retrieves the queued frames + from the AP. +*/ + +#define MAX_HIDDEN_SITES 4 +/*!< + max number of hidden SSID suuported by scan request +*/ + + +#define M2M_1X_USR_NAME_MAX 21 +/*!< The maximum size of the user name including the NULL termination. + It is used for RADIUS authentication in case of connecting the device to + an AP secured with WPA-Enterprise. +*/ + + +#define M2M_1X_PWD_MAX 41 +/*!< The maximum size of the password including the NULL termination. + It is used for RADIUS authentication in case of connecting the device to + an AP secured with WPA-Enterprise. +*/ + +#define M2M_CUST_IE_LEN_MAX 252 +/*!< The maximum size of IE (Information Element). +*/ + +#define PWR_DEFAULT PWR_HIGH +/********************* + * + * WIFI GROUP requests + */ + +#define M2M_CONFIG_CMD_BASE 1 +/*!< The base value of all the host configuration commands opcodes. +*/ +#define M2M_STA_CMD_BASE 40 +/*!< The base value of all the station mode host commands opcodes. +*/ +#define M2M_AP_CMD_BASE 70 +/*!< The base value of all the Access Point mode host commands opcodes. +*/ +#define M2M_P2P_CMD_BASE 90 +/*!< The base value of all the P2P mode host commands opcodes. +*/ +#define M2M_SERVER_CMD_BASE 100 +/*!< The base value of all the power save mode host commands codes. +*/ +/********************** + * OTA GROUP requests + */ +#define M2M_OTA_CMD_BASE 100 +/*!< The base value of all the OTA mode host commands opcodes. + * The OTA Have special group so can extended from 1-M2M_MAX_GRP_NUM_REQ +*/ +/*********************** + * + * CRYPTO group requests + */ +#define M2M_CRYPTO_CMD_BASE 1 +/*!< The base value of all the crypto mode host commands opcodes. + * The crypto Have special group so can extended from 1-M2M_MAX_GRP_NUM_REQ +*/ + +#define M2M_MAX_GRP_NUM_REQ (127) +/*!< max number of request in one group equal to 127 as the last bit reserved for config or data pkt +*/ + +#define WEP_40_KEY_STRING_SIZE ((uint8)10) +/*!< Indicate the wep key size in bytes for 40 bit string passphrase. +*/ + +#define WEP_104_KEY_STRING_SIZE ((uint8)26) +/*!< Indicate the wep key size in bytes for 104 bit string passphrase. +*/ +#define WEP_KEY_MAX_INDEX ((uint8)4) +/*!< Indicate the max key index value for WEP authentication +*/ +#define M2M_SHA256_CONTEXT_BUFF_LEN (128) +/*!< sha256 context size +*/ +#define M2M_SCAN_DEFAULT_NUM_SLOTS (2) +/*!< The default. number of scan slots performed by the WINC board. +*/ +#define M2M_SCAN_DEFAULT_SLOT_TIME (30) +/*!< The default. duration in miliseconds of a scan slots performed by the WINC board. +*/ +#define M2M_SCAN_DEFAULT_NUM_PROBE (2) +/*!< The default. number of scan slots performed by the WINC board. +*/ + + +/*======*======*======*======* + CONNECTION ERROR DEFINITIONS + *======*======*======*======*/ +typedef enum { + M2M_DEFAULT_CONN_INPROGRESS = ((sint8)-23), + /*!< + A failure that indicates that a default connection or forced connection is in progress + */ + M2M_DEFAULT_CONN_FAIL, + /*!< + A failure response that indicates that the winc failed to connect to the cached network + */ + M2M_DEFAULT_CONN_SCAN_MISMATCH, + /*!< + A failure response that indicates that no one of the cached networks + was found in the scan results, as a result to the function call m2m_default_connect. + */ + M2M_DEFAULT_CONN_EMPTY_LIST + /*!< + A failure response that indicates an empty network list as + a result to the function call m2m_default_connect. + */ + +}tenuM2mDefaultConnErrcode; + + + +/*======*======*======*======* + TLS DEFINITIONS + *======*======*======*======*/ +#define TLS_FILE_NAME_MAX 48 +/*!< Maximum length for each TLS certificate file name including null terminator. +*/ +#define TLS_SRV_SEC_MAX_FILES 8 +/*!< Maximum number of certificates allowed in TLS_SRV section. +*/ +#define TLS_SRV_SEC_START_PATTERN_LEN 8 +/*!< Length of certificate struct start pattern. +*/ +/*======*======*======*======* + OTA DEFINITIONS + *======*======*======*======*/ + +#define OTA_STATUS_VALID (0x12526285) +/*!< + Magic value updated in the Control structure in case of ROLLACK image Valid +*/ +#define OTA_STATUS_INVALID (0x23987718) +/*!< + Magic value updated in the Control structure in case of ROLLACK image InValid +*/ +#define OTA_MAGIC_VALUE (0x1ABCDEF9) +/*!< + Magic value set at the beginning of the OTA image header +*/ +#define M2M_MAGIC_APP (0xef522f61UL) +/*!< + Magic value set at the beginning of the Cortus OTA image header +*/ + +#define OTA_FORMAT_VER_0 (0) /*Till 19.2.2 format*/ +#define OTA_FORMAT_VER_1 (1) /*starting from 19.3.0 CRC is used and sequence number is used*/ +/*!< + Control structure format version +*/ +#define OTA_SHA256_DIGEST_SIZE (32) +/*!< + Sha256 digest size in the OTA image, + the sha256 digest is set at the beginning of image before the OTA header + */ + +/*======*======*======*======* + SSL DEFINITIONS + *======*======*======*======*/ + +#define TLS_CRL_DATA_MAX_LEN 64 +/* Every bit have 3dB gain control each. + for example: + 1 ->3db + 3 ->6db + 7 ->9db + */ + uint16 u8PPAGFor11GN; + /*!< PPA gain for 11GN (as the RF document represented) + PPA_AGC<0:2> Every bit have 3dB gain control each. + for example: + 1 ->3db + 3 ->6db + 7 ->9db + */ +}tstrM2mWifiGainsParams; + +/*! +@struct \ + tstrM2mWifiWepParams + +@brief + WEP security key parameters. +*/ +typedef struct{ + uint8 u8KeyIndx; + /*!< Wep key Index. + */ + uint8 u8KeySz; + /*!< Wep key Size. + */ + uint8 au8WepKey[WEP_104_KEY_STRING_SIZE + 1]; + /*!< WEP Key represented as a NULL terminated ASCII string. + */ + uint8 __PAD24__[3]; + /*!< Padding bytes to keep the structure word alligned. + */ +}tstrM2mWifiWepParams; + + +/*! +@struct \ + tstr1xAuthCredentials + +@brief + Credentials for the user to authenticate with the AAA server (WPA-Enterprise Mode IEEE802.1x). +*/ +typedef struct{ + uint8 au8UserName[M2M_1X_USR_NAME_MAX]; + /*!< User Name. It must be Null terminated string. + */ + uint8 au8Passwd[M2M_1X_PWD_MAX]; + /*!< Password corresponding to the user name. It must be Null terminated string. + */ +}tstr1xAuthCredentials; + + +/*! +@union \ + tuniM2MWifiAuth + +@brief + Wi-Fi Security Parameters for all supported security modes. +*/ +typedef union{ + uint8 au8PSK[M2M_MAX_PSK_LEN]; + /*!< Pre-Shared Key in case of WPA-Personal security. + */ + tstr1xAuthCredentials strCred1x; + /*!< Credentials for RADIUS server authentication in case of WPA-Enterprise security. + */ + tstrM2mWifiWepParams strWepInfo; + /*!< WEP key parameters in case of WEP security. + */ +}tuniM2MWifiAuth; + + +/*! +@struct \ + tstrM2MWifiSecInfo + +@brief + Authentication credentials to connect to a Wi-Fi network. +*/ +typedef struct{ + tuniM2MWifiAuth uniAuth; + /*!< Union holding all possible authentication parameters corresponding the current security types. + */ + uint8 u8SecType; + /*!< Wi-Fi network security type. See tenuM2mSecType for supported security types. + */ +#define __PADDING__ (4 - ((sizeof(tuniM2MWifiAuth) + 1) % 4)) + uint8 __PAD__[__PADDING__]; + /*!< Padding bytes for forcing 4-byte alignment + */ +}tstrM2MWifiSecInfo; + + +/*! +@struct \ + tstrM2mWifiConnect + +@brief + Wi-Fi Connect Request +*/ +typedef struct{ + tstrM2MWifiSecInfo strSec; + /*!< Security parameters for authenticating with the AP. + */ + uint16 u16Ch; + /*!< RF Channel for the target SSID. + */ + uint8 au8SSID[M2M_MAX_SSID_LEN]; + /*!< SSID of the desired AP. It must be NULL terminated string. + */ + uint8 u8NoSaveCred; +#define __CONN_PAD_SIZE__ (4 - ((sizeof(tstrM2MWifiSecInfo) + M2M_MAX_SSID_LEN + 3) % 4)) + uint8 __PAD__[__CONN_PAD_SIZE__]; + /*!< Padding bytes for forcing 4-byte alignment + */ +}tstrM2mWifiConnect; + + +/*! +@struct \ + tstrM2MWPSConnect + +@brief + WPS Configuration parameters + +@sa + tenuWPSTrigger +*/ +typedef struct { + uint8 u8TriggerType; + /*!< WPS triggering method (Push button or PIN) + */ + char acPinNumber[8]; + /*!< WPS PIN No (for PIN method) + */ + uint8 __PAD24__[3]; + /*!< Padding bytes for forcing 4-byte alignment + */ +}tstrM2MWPSConnect; + + +/*! +@struct \ + tstrM2MWPSInfo + +@brief WPS Result + + This structure is passed to the application in response to a WPS request. If the WPS session is completed successfully, the + structure will have Non-ZERO authentication type. If the WPS Session fails (due to error or timeout) the authentication type + is set to ZERO. + +@sa + tenuM2mSecType +*/ +typedef struct{ + uint8 u8AuthType; + /*!< Network authentication type. + */ + uint8 u8Ch; + /*!< RF Channel for the AP. + */ + uint8 au8SSID[M2M_MAX_SSID_LEN]; + /*!< SSID obtained from WPS. + */ + uint8 au8PSK[M2M_MAX_PSK_LEN]; + /*!< PSK for the network obtained from WPS. + */ +}tstrM2MWPSInfo; + + +/*! +@struct \ + tstrM2MDefaultConnResp + +@brief + Response error of the m2m_default_connect + +@sa + M2M_DEFAULT_CONN_SCAN_MISMATCH + M2M_DEFAULT_CONN_EMPTY_LIST +*/ +typedef struct{ + sint8 s8ErrorCode; + /*!< + Default connect error code. possible values are: + - M2M_DEFAULT_CONN_EMPTY_LIST + - M2M_DEFAULT_CONN_SCAN_MISMATCH + */ + uint8 __PAD24__[3]; +}tstrM2MDefaultConnResp; + +/*! +@struct \ + tstrM2MScanOption + +@brief + Scan options and configurations. + +@sa + tenuM2mScanCh + tstrM2MScan +*/ +typedef struct { + uint8 u8NumOfSlot; + /*|< The min number of slots is 2 for every channel, + every slot the soc will send Probe Request on air, and wait/listen for PROBE RESP/BEACONS for the u16slotTime + */ + uint8 u8SlotTime; + /*|< the time that the Soc will wait on every channel listening to the frames on air + when that time increaseed number of AP will increased in the scan results + min time is 10 ms and the max is 250 ms + */ + uint8 u8ProbesPerSlot; + /*!< Number of probe requests to be sent per channel scan slot. + */ + sint8 s8RssiThresh; + /*! < The RSSI threshold of the AP which will be connected to directly. + */ + +}tstrM2MScanOption; + +/*! +@struct \ + tstrM2MScanRegion + +@brief + Wi-Fi channel regulation region information. + +@sa + tenuM2mScanRegion +*/ +typedef struct { + uint16 u16ScanRegion; + /*|< Specifies the number of channels allowed in the region (e.g. North America = 11 ... etc.). + */ + uint8 __PAD16__[2]; + +}tstrM2MScanRegion; + +/*! +@struct \ + tstrM2MScan + +@brief + Wi-Fi Scan Request + +@sa + tenuM2mScanCh + tstrM2MScanOption +*/ +typedef struct { + uint8 u8ChNum; + /*!< The Wi-Fi RF Channel number + */ + uint8 __RSVD8__[1]; + /*!< Reserved for future use. + */ + uint16 u16PassiveScanTime; + /*!< Passive Scan Timeout in ms. The field is ignored for active scan. + */ +}tstrM2MScan; + +/*! +@struct \ + tstrCyptoResp + +@brief + crypto response +*/ +typedef struct { + sint8 s8Resp; + /***/ + uint8 __PAD24__[3]; + /* + */ +}tstrCyptoResp; + + +/*! +@struct \ + tstrM2mScanDone + +@brief + Wi-Fi Scan Result +*/ +typedef struct{ + uint8 u8NumofCh; + /*!< Number of found APs + */ + sint8 s8ScanState; + /*!< Scan status + */ + uint8 __PAD16__[2]; + /*!< Padding bytes for forcing 4-byte alignment + */ +}tstrM2mScanDone; + + +/*! +@struct \ + tstrM2mReqScanResult + +@brief Scan Result Request + + The Wi-Fi Scan results list is stored in Firmware. The application can request a certain scan result by its index. +*/ +typedef struct { + uint8 u8Index; + /*!< Index of the desired scan result + */ + uint8 __PAD24__[3]; + /*!< Padding bytes for forcing 4-byte alignment + */ +}tstrM2mReqScanResult; + + +/*! +@struct \ + tstrM2mWifiscanResult + +@brief Wi-Fi Scan Result + + Information corresponding to an AP in the Scan Result list identified by its order (index) in the list. +*/ +typedef struct { + uint8 u8index; + /*!< AP index in the scan result list. + */ + sint8 s8rssi; + /*!< AP signal strength. + */ + uint8 u8AuthType; + /*!< AP authentication type. + */ + uint8 u8ch; + /*!< AP RF channel. + */ + uint8 au8BSSID[6]; + /*!< BSSID of the AP. + */ + uint8 au8SSID[M2M_MAX_SSID_LEN]; + /*!< AP ssid. + */ + uint8 _PAD8_; + /*!< Padding bytes for forcing 4-byte alignment + */ +}tstrM2mWifiscanResult; + + +/*! +@struct \ + tstrM2mWifiStateChanged + +@brief + Wi-Fi Connection State + +@sa + M2M_WIFI_DISCONNECTED, M2M_WIFI_CONNECTED, M2M_WIFI_REQ_CON_STATE_CHANGED,tenuM2mConnChangedErrcode +*/ +typedef struct { + uint8 u8CurrState; + /*!< Current Wi-Fi connection state + */ + uint8 u8ErrCode; + /*!< Error type review tenuM2mConnChangedErrcode + */ + uint8 __PAD16__[2]; + /*!< Padding bytes for forcing 4-byte alignment + */ +}tstrM2mWifiStateChanged; + + +/*! +@struct \ + tstrM2mPsType + +@brief + Power Save Configuration + +@sa + tenuPowerSaveModes +*/ +typedef struct{ + uint8 u8PsType; + /*!< Power save operating mode + */ + uint8 u8BcastEn; + /*!< + */ + uint8 __PAD16__[2]; + /*!< Padding bytes for forcing 4-byte alignment + */ +}tstrM2mPsType; + +/*! +@struct \ + tstrM2mSlpReqTime + +@brief + Manual power save request sleep time + +*/ +typedef struct { + /*!< Sleep time in ms + */ + uint32 u32SleepTime; + +} tstrM2mSlpReqTime; + +/*! +@struct \ + tstrM2mLsnInt + +@brief Listen interval + + It is the value of the Wi-Fi STA listen interval for power saving. It is given in units of Beacon period. + Periodically after the listen interval fires, the WINC is wakeup and listen to the beacon and check for any buffered frames for it from the AP. +*/ +typedef struct { + uint16 u16LsnInt; + /*!< Listen interval in Beacon period count. + */ + uint8 __PAD16__[2]; + /*!< Padding bytes for forcing 4-byte alignment + */ +}tstrM2mLsnInt; + + +/*! +@struct \ + tstrM2MWifiMonitorModeCtrl + +@brief Wi-Fi Monitor Mode Filter + + This structure sets the filtering criteria for WLAN packets when monitoring mode is enable. + The received packets matching the filtering parameters, are passed directly to the application. +*/ +typedef struct{ + uint8 u8ChannelID; + /* !< RF Channel ID. It must use values from tenuM2mScanCh + */ + uint8 u8FrameType; + /*!< It must use values from tenuWifiFrameType. + */ + uint8 u8FrameSubtype; + /*!< It must use values from tenuSubTypes. + */ + uint8 au8SrcMacAddress[6]; + /* ZERO means DO NOT FILTER Source address. + */ + uint8 au8DstMacAddress[6]; + /* ZERO means DO NOT FILTER Destination address. + */ + uint8 au8BSSID[6]; + /* ZERO means DO NOT FILTER BSSID. + */ + uint8 u8EnRecvHdr; + /* + Enable recv the full hder before the payload + */ + uint8 __PAD16__[2]; + /*!< Padding bytes for forcing 4-byte alignment + */ +}tstrM2MWifiMonitorModeCtrl; + + +/*! +@struct \ + tstrM2MWifiRxPacketInfo + +@brief Wi-Fi RX Frame Header + + The M2M application has the ability to allow Wi-Fi monitoring mode for receiving all Wi-Fi Raw frames matching a well defined filtering criteria. + When a target Wi-Fi packet is received, the header information are extracted and assigned in this structure. +*/ +typedef struct{ + uint8 u8FrameType; + /*!< It must use values from tenuWifiFrameType. + */ + uint8 u8FrameSubtype; + /*!< It must use values from tenuSubTypes. + */ + uint8 u8ServiceClass; + /*!< Service class from Wi-Fi header. + */ + uint8 u8Priority; + /*!< Priority from Wi-Fi header. + */ + uint8 u8HeaderLength; + /*!< Frame Header length. + */ + uint8 u8CipherType; + /*!< Encryption type for the rx packet. + */ + uint8 au8SrcMacAddress[6]; + /* ZERO means DO NOT FILTER Source address. + */ + uint8 au8DstMacAddress[6]; + /* ZERO means DO NOT FILTER Destination address. + */ + uint8 au8BSSID[6]; + /* ZERO means DO NOT FILTER BSSID. + */ + uint16 u16DataLength; + /*!< Data payload length (Header excluded). + */ + uint16 u16FrameLength; + /*!< Total frame length (Header + Data). + */ + uint32 u32DataRateKbps; + /*!< Data Rate in Kbps. + */ + sint8 s8RSSI; + /*!< RSSI. + */ + uint8 __PAD24__[3]; + /*!< Padding bytes for forcing 4-byte alignment + */ +}tstrM2MWifiRxPacketInfo; + + +/*! +@struct \ + tstrM2MWifiTxPacketInfo + +@brief Wi-Fi TX Packet Info + + The M2M Application has the ability to compose a RAW Wi-Fi frames (under the application responsibility). + When transmitting a Wi-Fi packet, the application must supply the firmware with this structure for sending the target frame. +*/ +typedef struct{ + uint16 u16PacketSize; + /*!< Wlan frame length. + */ + uint16 u16HeaderLength; + /*!< Wlan frame header length. + */ +}tstrM2MWifiTxPacketInfo; + + +/*! + @struct \ + tstrM2MP2PConnect + + @brief + Set the device to operate in the Wi-Fi Direct (P2P) mode. +*/ +typedef struct { + uint8 u8ListenChannel; + /*!< P2P Listen Channel (1, 6 or 11) + */ + uint8 __PAD24__[3]; + /*!< Padding bytes for forcing 4-byte alignment + */ +}tstrM2MP2PConnect; + +/*! +@struct \ + tstrM2MAPConfig + +@brief AP Configuration + + This structure holds the configuration parameters for the M2M AP mode. It should be set by the application when + it requests to enable the M2M AP operation mode. The M2M AP mode currently supports only WEP security (with + the NO Security option available of course). +*/ +typedef struct { + /*!< + Configuration parameters for the WiFi AP. + */ + uint8 au8SSID[M2M_MAX_SSID_LEN]; + /*!< AP SSID + */ + uint8 u8ListenChannel; + /*!< Wi-Fi RF Channel which the AP will operate on + */ + uint8 u8KeyIndx; + /*!< Wep key Index + */ + uint8 u8KeySz; + /*!< Wep/WPA key Size + */ + uint8 au8WepKey[WEP_104_KEY_STRING_SIZE + 1]; + /*!< Wep key + */ + uint8 u8SecType; + /*!< Security type: Open or WEP or WPA in the current implementation + */ + uint8 u8SsidHide; + /*!< SSID Status "Hidden(1)/Visible(0)" + */ + uint8 au8DHCPServerIP[4]; + /*!< Ap IP server address + */ + uint8 au8Key[M2M_MAX_PSK_LEN]; + /*!< WPA key + */ + uint8 __PAD24__[2]; + /*!< Padding bytes for forcing alignment + */ +}tstrM2MAPConfig; + + +/*! +@struct \ + tstrM2mServerInit + +@brief + PS Server initialization. +*/ +typedef struct { + uint8 u8Channel; + /*!< Server Listen channel + */ + uint8 __PAD24__[3]; + /*!< Padding bytes for forcing 4-byte alignment + */ +}tstrM2mServerInit; + + +/*! +@struct \ + tstrM2mClientState + +@brief + PS Client State. +*/ +typedef struct { + uint8 u8State; + /*!< PS Client State + */ + uint8 __PAD24__[3]; + /*!< Padding bytes for forcing 4-byte alignment + */ +}tstrM2mClientState; + + +/*! +@struct \ + tstrM2Mservercmd + +@brief + PS Server CMD +*/ +typedef struct { + uint8 u8cmd; + /*!< PS Server Cmd + */ + uint8 __PAD24__[3]; + /*!< Padding bytes for forcing 4-byte alignment + */ +}tstrM2Mservercmd; + + +/*! +@struct \ + tstrM2mSetMacAddress + +@brief + Sets the MAC address from application. The WINC load the mac address from the effuse by default to the WINC configuration memory, + but that function is used to let the application overwrite the configuration memory with the mac address from the host. + +@note + It's recommended to call this only once before calling connect request and after the m2m_wifi_init +*/ +typedef struct { + uint8 au8Mac[6]; + /*!< MAC address array + */ + uint8 __PAD16__[2]; + /*!< Padding bytes for forcing 4-byte alignment + */ +}tstrM2mSetMacAddress; + + +/*! +@struct \ + tstrM2MDeviceNameConfig + +@brief Device name + + It is assigned by the application. It is used mainly for Wi-Fi Direct device + discovery and WPS device information. +*/ +typedef struct { + uint8 au8DeviceName[M2M_DEVICE_NAME_MAX]; + /*!< NULL terminated device name + */ +}tstrM2MDeviceNameConfig; + + +/*! +@struct \ + tstrM2MIPConfig + +@brief + Static IP configuration. + +@note + All member IP addresses are expressed in Network Byte Order (eg. "192.168.10.1" will be expressed as 0x010AA8C0). + */ +typedef struct { + uint32 u32StaticIP; + /*!< The static IP assigned to the device. + */ + uint32 u32Gateway; + /*!< IP of the Default internet gateway. + */ + uint32 u32DNS; + /*!< IP for the DNS server. + */ + uint32 u32SubnetMask; + /*!< Subnet mask for the local area network. + */ + uint32 u32DhcpLeaseTime; + /*!< Dhcp Lease Time in sec + */ +} tstrM2MIPConfig; + +/*! +@struct \ + tstrM2mIpRsvdPkt + +@brief + Received Packet Size and Data Offset + + */ +typedef struct{ + uint16 u16PktSz; + uint16 u16PktOffset; +} tstrM2mIpRsvdPkt; + + +/*! +@struct \ + tstrM2MProvisionModeConfig + +@brief + M2M Provisioning Mode Configuration + */ + +typedef struct { + tstrM2MAPConfig strApConfig; + /*!< + Configuration parameters for the WiFi AP. + */ + char acHttpServerDomainName[64]; + /*!< + The device domain name for HTTP provisioning. + */ + uint8 u8EnableRedirect; + /*!< + A flag to enable/disable HTTP redirect feature for the HTTP Provisioning server. If the Redirect is enabled, + all HTTP traffic (http://URL) from the device associated with WINC AP will be redirected to the HTTP Provisioning Web page. + - 0 : Disable HTTP Redirect. + - 1 : Enable HTTP Redirect. + */ + uint8 __PAD24__[3]; +}tstrM2MProvisionModeConfig; + + +/*! +@struct \ + tstrM2MProvisionInfo + +@brief + M2M Provisioning Information obtained from the HTTP Provisioning server. + */ +typedef struct{ + uint8 au8SSID[M2M_MAX_SSID_LEN]; + /*!< + Provisioned SSID. + */ + uint8 au8Password[M2M_MAX_PSK_LEN]; + /*!< + Provisioned Password. + */ + uint8 u8SecType; + /*!< + Wifi Security type. + */ + uint8 u8Status; + /*!< + Provisioning status. It must be checked before reading the provisioning information. It may be + - M2M_SUCCESS : Provision successful. + - M2M_FAIL : Provision Failed. + */ +}tstrM2MProvisionInfo; + + +/*! +@struct \ + tstrM2MConnInfo + +@brief + M2M Provisioning Information obtained from the HTTP Provisioning server. + */ +typedef struct{ + char acSSID[M2M_MAX_SSID_LEN]; + /*!< AP connection SSID name */ + uint8 u8SecType; + /*!< Security type */ + uint8 au8IPAddr[4]; + /*!< Connection IP address */ + uint8 au8MACAddress[6]; + /*!< MAC address of the peer Wi-Fi station */ + sint8 s8RSSI; + /*!< Connection RSSI signal */ + uint8 __PAD24__[3]; + /*!< Padding bytes for forcing 4-byte alignment */ +}tstrM2MConnInfo; + +/*! +@struct \ + tstrOtaInitHdr + +@brief + OTA Image Header + */ + +typedef struct{ + uint32 u32OtaMagicValue; + /*!< Magic value kept in the OTA image after the + sha256 Digest buffer to define the Start of OTA Header */ + uint32 u32OtaPayloadSzie; + /*!< + The Total OTA image payload size, include the sha256 key size + */ + +}tstrOtaInitHdr; + + +/*! +@struct \ + tstrOtaControlSec + +@brief + Control section structure is used to define the working image and + the validity of the roll-back image and its offset, also both firmware versions is kept in that structure. + */ + +typedef struct { + uint32 u32OtaMagicValue; +/*!< + Magic value used to ensure the structure is valid or not +*/ + uint32 u32OtaFormatVersion; +/*!< + NA NA NA Flash version cs struct version + 00 00 00 00 00 + Control structure format version, the value will be incremented in case of structure changed or updated +*/ + uint32 u32OtaSequenceNumber; +/*!< + Sequence number is used while update the control structure to keep track of how many times that section updated +*/ + uint32 u32OtaLastCheckTime; +/*!< + Last time OTA check for update +*/ + uint32 u32OtaCurrentworkingImagOffset; +/*!< + Current working offset in flash +*/ + uint32 u32OtaCurrentworkingImagFirmwareVer; +/*!< + current working image version ex 18.0.1 +*/ + uint32 u32OtaRollbackImageOffset; +/*!< + Roll-back image offset in flash +*/ + uint32 u32OtaRollbackImageValidStatus; +/*!< + roll-back image valid status +*/ + uint32 u32OtaRollbackImagFirmwareVer; +/*!< + Roll-back image version (ex 18.0.3) +*/ + uint32 u32OtaCortusAppWorkingOffset; +/*!< + cortus app working offset in flash +*/ + uint32 u32OtaCortusAppWorkingValidSts; +/*!< + Working Cortus app valid status +*/ + uint32 u32OtaCortusAppWorkingVer; +/*!< + Working cortus app version (ex 18.0.3) +*/ + uint32 u32OtaCortusAppRollbackOffset; +/*!< + cortus app rollback offset in flash +*/ + uint32 u32OtaCortusAppRollbackValidSts; +/*!< + roll-back cortus app valid status +*/ + uint32 u32OtaCortusAppRollbackVer; +/*!< + Roll-back cortus app version (ex 18.0.3) +*/ + uint32 u32OtaControlSecCrc; +/*!< + CRC for the control structure to ensure validity +*/ +} tstrOtaControlSec; + +/*! +@enum \ + tenuOtaUpdateStatus + +@brief + OTA return status +*/ +typedef enum { + OTA_STATUS_SUCSESS = 0, + /*!< OTA Success with not errors. */ + OTA_STATUS_FAIL = 1, + /*!< OTA generic fail. */ + OTA_STATUS_INVAILD_ARG = 2, + /*!< Invalid or malformed download URL. */ + OTA_STATUS_INVAILD_RB_IMAGE = 3, + /*!< Invalid rollback image. */ + OTA_STATUS_INVAILD_FLASH_SIZE = 4, + /*!< Flash size on device is not enough for OTA. */ + OTA_STATUS_AlREADY_ENABLED = 5, + /*!< An OTA operation is already enabled. */ + OTA_STATUS_UPDATE_INPROGRESS = 6, + /*!< An OTA operation update is in progress */ + OTA_STATUS_IMAGE_VERIF_FAILED = 7, + /*!< OTA Verfication failed */ + OTA_STATUS_CONNECTION_ERROR = 8, + /*!< OTA connection error */ + OTA_STATUS_SERVER_ERROR = 9, + /*!< OTA server Error (file not found or else ...) */ + OTA_STATUS_ABORTED = 10 + /*!< OTA download has been aborted by the application. */ +} tenuOtaUpdateStatus; +/*! +@enum \ + tenuOtaUpdateStatusType + +@brief + OTA update Status type +*/ +typedef enum { + + DL_STATUS = 1, + /*!< Download OTA file status + */ + SW_STATUS = 2, + /*!< Switching to the upgrade firmware status + */ + RB_STATUS = 3, + /*!< Roll-back status + */ + AB_STATUS = 4 + /*!< Abort status + */ +}tenuOtaUpdateStatusType; + + +/*! +@struct \ + tstrOtaUpdateStatusResp + +@brief + OTA Update Information + +@sa + tenuWPSTrigger +*/ +typedef struct { + uint8 u8OtaUpdateStatusType; + /*!< + Status type tenuOtaUpdateStatusType + */ + uint8 u8OtaUpdateStatus; + /*!< + OTA_SUCCESS + OTA_ERR_WORKING_IMAGE_LOAD_FAIL + OTA_ERR_INVAILD_CONTROL_SEC + M2M_ERR_OTA_SWITCH_FAIL + M2M_ERR_OTA_START_UPDATE_FAIL + M2M_ERR_OTA_ROLLBACK_FAIL + M2M_ERR_OTA_INVAILD_FLASH_SIZE + M2M_ERR_OTA_INVAILD_ARG + */ + uint8 _PAD16_[2]; +}tstrOtaUpdateStatusResp; + +/*! +@struct \ + tstrOtaUpdateInfo + +@brief + OTA Update Information + +@sa + tenuWPSTrigger +*/ +typedef struct { + uint32 u8NcfUpgradeVersion; + /*!< NCF OTA Upgrade Version + */ + uint32 u8NcfCurrentVersion; + /*!< NCF OTA Current firmware version + */ + uint32 u8NcdUpgradeVersion; + /*!< NCD (host) upgraded version (if the u8NcdRequiredUpgrade == true) + */ + uint8 u8NcdRequiredUpgrade; + /*!< NCD Required upgrade to the above version + */ + uint8 u8DownloadUrlOffset; + /*!< Download URL offset in the received packet + */ + uint8 u8DownloadUrlSize; + /*!< Download URL size in the received packet + */ + uint8 __PAD8__; + /*!< Padding bytes for forcing 4-byte alignment + */ +} tstrOtaUpdateInfo; + +/*! +@struct \ + tstrSystemTime + +@brief + Used for time storage. +*/ +typedef struct{ + uint16 u16Year; + uint8 u8Month; + uint8 u8Day; + uint8 u8Hour; + uint8 u8Minute; + uint8 u8Second; + uint8 __PAD8__; +}tstrSystemTime; + +/*! +@struct \ + tstrM2MMulticastMac + +@brief + M2M add/remove multi-cast mac address + */ + typedef struct { + uint8 au8macaddress[M2M_MAC_ADDRES_LEN]; + /*!< + Mac address needed to be added or removed from filter. + */ + uint8 u8AddRemove; + /*!< + set by 1 to add or 0 to remove from filter. + */ + uint8 __PAD8__; + /*!< Padding bytes for forcing 4-byte alignment + */ +}tstrM2MMulticastMac; + +/*! +@struct \ + tstrPrng + +@brief + M2M Request PRNG + */ + typedef struct { + /*!< + return buffer address + */ + uint8 *pu8RngBuff; + /*!< + PRNG size requested + */ + uint16 u16PrngSize; + /*!< + PRNG pads + */ + uint8 __PAD16__[2]; +}tstrPrng; + +/* + * TLS certificate revocation list + * Typedefs common between fw and host + */ + +/*! +@struct \ + tstrTlsCrlEntry + +@brief + Certificate data for inclusion in a revocation list (CRL) +*/ +typedef struct { + uint8 u8DataLen; + /*!< + Length of certificate data (maximum possible is @ref TLS_CRL_DATA_MAX_LEN) + */ + uint8 au8Data[TLS_CRL_DATA_MAX_LEN]; + /*!< + Certificate data + */ + uint8 __PAD24__[3]; + /*!< + Padding bytes for forcing 4-byte alignment + */ +}tstrTlsCrlEntry; + +/*! +@struct \ + tstrTlsCrlInfo + +@brief + Certificate revocation list details +*/ +typedef struct { + uint8 u8CrlType; + /*!< + Type of certificate data contained in list + */ + uint8 u8Rsv1; + /*!< + Reserved for future use + */ + uint8 u8Rsv2; + /*!< + Reserved for future use + */ + uint8 u8Rsv3; + /*!< + Reserved for future use + */ + tstrTlsCrlEntry astrTlsCrl[TLS_CRL_MAX_ENTRIES]; + /*!< + List entries + */ +}tstrTlsCrlInfo; + + /*! +@enum\ + tenuSslCertExpSettings + +@brief SSL Certificate Expiry Validation Options +*/ +typedef enum{ + SSL_CERT_EXP_CHECK_DISABLE, + /*!< + ALWAYS OFF. + Ignore certificate expiration date validation. If a certificate is + expired or there is no configured system time, the SSL connection SUCCEEDs. + */ + SSL_CERT_EXP_CHECK_ENABLE, + /*!< + ALWAYS ON. + Validate certificate expiration date. If a certificate is expired or + there is no configured system time, the SSL connection FAILs. + */ + SSL_CERT_EXP_CHECK_EN_IF_SYS_TIME + /*!< + CONDITIONAL VALIDATION (Default setting at startup). + Validate the certificate expiration date only if there is a configured system time. + If there is no configured system time, the certificate expiration is bypassed and the + SSL connection SUCCEEDs. + */ +}tenuSslCertExpSettings; + + +/*! +@struct \ + tstrTlsSrvSecFileEntry + +@brief + This struct contains a TLS certificate. + */ +typedef struct{ + char acFileName[TLS_FILE_NAME_MAX]; + /*!< Name of the certificate. */ + uint32 u32FileSize; + /*!< Size of the certificate. */ + uint32 u32FileAddr; + /*!< Error Code. */ +}tstrTlsSrvSecFileEntry; + +/*! +@struct \ + tstrTlsSrvSecHdr + +@brief + This struct contains a set of TLS certificates. + */ +typedef struct{ + uint8 au8SecStartPattern[TLS_SRV_SEC_START_PATTERN_LEN]; + /*!< Start pattern. */ + uint32 u32nEntries; + /*!< Number of certificates stored in the struct. */ + uint32 u32NextWriteAddr; + /*!< TLS Certificates. */ + tstrTlsSrvSecFileEntry astrEntries[TLS_SRV_SEC_MAX_FILES]; +}tstrTlsSrvSecHdr; + +typedef struct{ + uint32 u32CsBMP; +}tstrSslSetActiveCsList; + + + /**@}*/ + +#endif diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/include/m2m_wifi.h b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/include/m2m_wifi.h new file mode 100644 index 0000000000000..3477196c100d9 --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/include/m2m_wifi.h @@ -0,0 +1,2882 @@ +/** + * + * \file + * + * \brief WINC WLAN Application Interface. + * + * Copyright (c) 2016-2017 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + +#ifndef __M2M_WIFI_H__ +#define __M2M_WIFI_H__ + +/** \defgroup m2m_wifi WLAN + * + */ + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +INCLUDES +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ + +#include "common/include/nm_common.h" +#include "driver/include/m2m_types.h" +#include "driver/source/nmdrv.h" + +#ifdef CONF_MGMT + + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +MACROS +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ +/**@defgroup WlanEnums DataTypes + * @ingroup m2m_wifi + * @{*/ +/*! +@enum \ + tenuWifiFrameType + +@brief + Enumeration for Wi-Fi MAC frame type codes (2-bit) + The following types are used to identify the type of frame sent or received. + Each frame type constitutes a number of frame subtypes as defined in @ref tenuSubTypes to specify the exact type of frame. + Values are defined as per the IEEE 802.11 standard. + +@remarks + The following frame types are useful for advanced user usage when monitoring mode is used (defining @ref CONF_MGMT) + and the user application requires to monitor the frame transmission and reception. +@see + tenuSubTypes +*/ +typedef enum { + MANAGEMENT = 0x00, + /*!< Wi-Fi Management frame (Probe Req/Resp, Beacon, Association Req/Resp ...etc). + */ + CONTROL = 0x04, + /*!< Wi-Fi Control frame (eg. ACK frame). + */ + DATA_BASICTYPE = 0x08, + /*!< Wi-Fi Data frame. + */ + RESERVED = 0x0C, + + M2M_WIFI_FRAME_TYPE_ANY = 0xFF +/*!< Set monitor mode to receive any of the frames types +*/ +}tenuWifiFrameType; + + +/*! +@enum \ + tenuSubTypes + +@brief + Enumeration for Wi-Fi MAC Frame subtype code (6-bit). + The frame subtypes fall into one of the three frame type groups as defined in @ref tenuWifiFrameType + (MANAGEMENT, CONTROL & DATA). + Values are defined as per the IEEE 802.11 standard. +@remarks + The following sub-frame types are useful for advanced user usage when @ref CONF_MGMT is defined + and the application developer requires to monitor the frame transmission and reception. +@see + tenuWifiFrameType + tstrM2MWifiMonitorModeCtrl +*/ +typedef enum { + /*!< Sub-Types related to Management Sub-Types */ + ASSOC_REQ = 0x00, + ASSOC_RSP = 0x10, + REASSOC_REQ = 0x20, + REASSOC_RSP = 0x30, + PROBE_REQ = 0x40, + PROBE_RSP = 0x50, + BEACON = 0x80, + ATIM = 0x90, + DISASOC = 0xA0, + AUTH = 0xB0, + DEAUTH = 0xC0, + ACTION = 0xD0, +/**@{*/ + /* Sub-Types related to Control */ + PS_POLL = 0xA4, + RTS = 0xB4, + CTS = 0xC4, + ACK = 0xD4, + CFEND = 0xE4, + CFEND_ACK = 0xF4, + BLOCKACK_REQ = 0x84, + BLOCKACK = 0x94, +/**@{*/ + /* Sub-Types related to Data */ + DATA = 0x08, + DATA_ACK = 0x18, + DATA_POLL = 0x28, + DATA_POLL_ACK = 0x38, + NULL_FRAME = 0x48, + CFACK = 0x58, + CFPOLL = 0x68, + CFPOLL_ACK = 0x78, + QOS_DATA = 0x88, + QOS_DATA_ACK = 0x98, + QOS_DATA_POLL = 0xA8, + QOS_DATA_POLL_ACK = 0xB8, + QOS_NULL_FRAME = 0xC8, + QOS_CFPOLL = 0xE8, + QOS_CFPOLL_ACK = 0xF8, + M2M_WIFI_FRAME_SUB_TYPE_ANY = 0xFF + /*!< Set monitor mode to receive any of the frames types + */ +}tenuSubTypes; + + +/*! +@enum \ + tenuInfoElementId + +@brief + Enumeration for the Wi-Fi Information Element(IE) IDs, which indicates the specific type of IEs. + IEs are management frame information included in management frames. + Values are defined as per the IEEE 802.11 standard. + +*/ +typedef enum { + ISSID = 0, + /*!< Service Set Identifier (SSID) + */ + ISUPRATES = 1, + /*!< Supported Rates + */ + IFHPARMS = 2, + /*!< FH parameter set + */ + IDSPARMS = 3, + /*!< DS parameter set + */ + ICFPARMS = 4, + /*!< CF parameter set + */ + ITIM = 5, + /*!< Traffic Information Map + */ + IIBPARMS = 6, + /*!< IBSS parameter set + */ + ICOUNTRY = 7, + /*!< Country element. + */ + IEDCAPARAMS = 12, + /*!< EDCA parameter set + */ + ITSPEC = 13, + /*!< Traffic Specification + */ + ITCLAS = 14, + /*!< Traffic Classification + */ + ISCHED = 15, + /*!< Schedule. + */ + ICTEXT = 16, + /*!< Challenge Text + */ + IPOWERCONSTRAINT = 32, + /*!< Power Constraint. + */ + IPOWERCAPABILITY = 33, + /*!< Power Capability + */ + ITPCREQUEST = 34, + /*!< TPC Request + */ + ITPCREPORT = 35, + /*!< TPC Report + */ + ISUPCHANNEL = 36, + /* Supported channel list + */ + ICHSWANNOUNC = 37, + /*!< Channel Switch Announcement + */ + IMEASUREMENTREQUEST = 38, + /*!< Measurement request + */ + IMEASUREMENTREPORT = 39, + /*!< Measurement report + */ + IQUIET = 40, + /*!< Quiet element Info + */ + IIBSSDFS = 41, + /*!< IBSS DFS + */ + IERPINFO = 42, + /*!< ERP Information + */ + ITSDELAY = 43, + /*!< TS Delay + */ + ITCLASPROCESS = 44, + /*!< TCLAS Processing + */ + IHTCAP = 45, + /*!< HT Capabilities + */ + IQOSCAP = 46, + /*!< QoS Capability + */ + IRSNELEMENT = 48, + /*!< RSN Information Element + */ + IEXSUPRATES = 50, + /*!< Extended Supported Rates + */ + IEXCHSWANNOUNC = 60, + /*!< Extended Ch Switch Announcement + */ + IHTOPERATION = 61, + /*!< HT Information + */ + ISECCHOFF = 62, + /*!< Secondary Channel Offset + */ + I2040COEX = 72, + /*!< 20/40 Coexistence IE + */ + I2040INTOLCHREPORT = 73, + /*!< 20/40 Intolerant channel report + */ + IOBSSSCAN = 74, + /*!< OBSS Scan parameters + */ + IEXTCAP = 127, + /*!< Extended capability + */ + IWMM = 221, + /*!< WMM parameters + */ + IWPAELEMENT = 221 + /*!< WPA Information Element + */ +}tenuInfoElementId; + + +/*! +@struct \ + tenuWifiCapability + +@brief + Enumeration for capability Information field bit. + The value of the capability information field from the 802.11 management frames received by the wireless LAN interface. + Defining the capabilities of the Wi-Fi system. Values are defined as per the IEEE 802.11 standard. + +@details + Capabilities:- + ESS/IBSS : Defines whether a frame is coming from an AP or not. + POLLABLE : CF Poll-able + POLLREQ : Request to be polled + PRIVACY : WEP encryption supported + SHORTPREAMBLE : Short Preamble is supported + SHORTSLOT : Short Slot is supported + PBCC :PBCC + CHANNELAGILITY :Channel Agility + SPECTRUM_MGMT :Spectrum Management + DSSS_OFDM : DSSS-OFDM +*/ +typedef enum{ + ESS = 0x01, + /*!< ESS capability + */ + IBSS = 0x02, + /*!< IBSS mode + */ + POLLABLE = 0x04, + /*!< CF Pollable + */ + POLLREQ = 0x08, + /*!< Request to be polled + */ + PRIVACY = 0x10, + /*!< WEP encryption supported + */ + SHORTPREAMBLE = 0x20, + /*!< Short Preamble is supported + */ + SHORTSLOT = 0x400, + /*!< Short Slot is supported + */ + PBCC = 0x40, + /*!< PBCC + */ + CHANNELAGILITY = 0x80, + /*!< Channel Agility + */ + SPECTRUM_MGMT = 0x100, + /*!< Spectrum Management + */ + DSSS_OFDM = 0x2000 + /*!< DSSS-OFDM + */ +}tenuWifiCapability; + + +#endif + +/*! +@typedef \ + tpfAppWifiCb + +@brief + Wi-Fi's main callback function handler, for handling the M2M_WIFI events received on the Wi-Fi interface. + Such notifications are received in response to Wi-Fi/P2P operations such as @ref m2m_wifi_request_scan, + @ref m2m_wifi_connect. + Wi-Fi/P2P operations are implemented in an asynchronous mode, and all incoming information/status + are to be handled through this callback function when the corresponding notification is received. + Applications are expected to assign this wi-fi callback function by calling @ref m2m_wifi_init +@param [in] u8MsgType + Type of notifications. Possible types are: + /ref M2M_WIFI_RESP_CON_STATE_CHANGED + /ref M2M_WIFI_RESP_CONN_INFO + /ref M2M_WIFI_REQ_DHCP_CONF + /ref M2M_WIFI_REQ_WPS + /ref M2M_WIFI_RESP_IP_CONFLICT + /ref M2M_WIFI_RESP_SCAN_DONE + /ref M2M_WIFI_RESP_SCAN_RESULT + /ref M2M_WIFI_RESP_CURRENT_RSSI + /ref M2M_WIFI_RESP_CLIENT_INFO + /ref M2M_WIFI_RESP_PROVISION_INFO + /ref M2M_WIFI_RESP_DEFAULT_CONNECT + + In case Ethernet/Bypass mode is defined : + @ref M2M_WIFI_RESP_ETHERNET_RX_PACKET + + In case monitoring mode is used: + @ref M2M_WIFI_RESP_WIFI_RX_PACKET + +@param [in] pvMsg + A pointer to a buffer containing the notification parameters (if any). It should be + casted to the correct data type corresponding to the notification type. + +@see + tstrM2mWifiStateChanged + tstrM2MWPSInfo + tstrM2mScanDone + tstrM2mWifiscanResult +*/ +typedef void (*tpfAppWifiCb) (uint8 u8MsgType, void * pvMsg); + +/*! +@typedef \ + tpfAppEthCb + +@brief + ETHERNET (bypass mode) notification callback function receiving Bypass mode events as defined in + the Wi-Fi responses enumeration @ref tenuM2mStaCmd. + +@param [in] u8MsgType + Type of notification. Possible types are: + - [M2M_WIFI_RESP_ETHERNET_RX_PACKET](@ref M2M_WIFI_RESP_ETHERNET_RX_PACKET) + +@param [in] pvMsg + A pointer to a buffer containing the notification parameters (if any). It should be + casted to the correct data type corresponding to the notification type. + For example, it could be a pointer to the buffer holding the received frame in case of @ref M2M_WIFI_RESP_ETHERNET_RX_PACKET + event. + +@param [in] pvControlBuf + A pointer to control buffer describing the accompanied message. + To be casted to @ref tstrM2mIpCtrlBuf in case of @ref M2M_WIFI_RESP_ETHERNET_RX_PACKET event. + +@warning + Make sure that the application defines @ref ETH_MODE. + +@see + m2m_wifi_init + +*/ +typedef void (*tpfAppEthCb) (uint8 u8MsgType, void * pvMsg,void * pvCtrlBuf); + +/*! +@typedef \ + tpfAppMonCb + +@brief + Wi-Fi monitoring mode callback function. This function delivers all received wi-Fi packets through the Wi-Fi interface. + Applications requiring to operate in the monitoring should call the asynchronous function m2m_wifi_enable_monitoring_mode + and expect to receive the Wi-Fi packets through this callback function, when the event is received. + To disable the monitoring mode a call to @ref m2m_wifi_disable_monitoring_mode should be made. +@param [in] pstrWifiRxPacket + Pointer to a structure holding the Wi-Fi packet header parameters. + +@param [in] pu8Payload + Pointer to the buffer holding the Wi-Fi packet payload information required by the application starting from the + defined OFFSET by the application (when calling m2m_wifi_enable_monitoring_mode). + Could hold a value of NULL, if the application does not need any data from the payload. + +@param [in] u16PayloadSize + The size of the payload in bytes. + +@see + m2m_wifi_enable_monitoring_mode,m2m_wifi_init + +@warning + u16PayloadSize should not exceed the buffer size given through m2m_wifi_enable_monitoring_mode. + +*/ +typedef void (*tpfAppMonCb) (tstrM2MWifiRxPacketInfo *pstrWifiRxPacket, uint8 * pu8Payload, uint16 u16PayloadSize); + +/** +@struct \ + tstrEthInitParam + +@brief + Structure to hold Ethernet interface parameters. + Structure is to be defined and have its attributes set,based on the application's functionality before + a call is made to initialize the Wi-Fi operations by calling the @ref m2m_wifi_init function. + This structure is part of the Wi-Fi configuration structure @ref tstrWifiInitParam. + Applications shouldn't need to define this structure, if the bypass mode is not defined. + +@see + tpfAppEthCb + tpfAppWifiCb + m2m_wifi_init + +@warning + Make sure that application defines @ref ETH_MODE before using @ref tstrEthInitParam. + +*/ +typedef struct { + tpfAppWifiCb pfAppWifiCb; + /*!< + Callback for wifi notifications. + */ + tpfAppEthCb pfAppEthCb; + /*!< + Callback for Ethernet interface. + */ + uint8 * au8ethRcvBuf; + /*!< + Pointer to Receive Buffer of Ethernet Packet + */ + uint16 u16ethRcvBufSize; + /*!< + Size of Receive Buffer for Ethernet Packet + */ + uint8 u8EthernetEnable; + /*!< + Enable Ethernet mode flag + */ + uint8 __PAD8__; + /*!< + Padding + */ +} tstrEthInitParam; +/*! +@struct \ + tstrM2mIpCtrlBuf + +@brief + Structure holding the incoming buffer's data size information, indicating the data size of the buffer and the remaining buffer's data size . + The data of the buffer which holds the packet sent to the host when in the bypass mode, is placed in the @ref tstrEthInitParam structure in the + @ref au8ethRcvBuf attribute. This following information is retrieved in the host when an event @ref M2M_WIFI_RESP_ETHERNET_RX_PACKET is received in + the Wi-Fi callback function @ref tpfAppWifiCb. + + The application is expected to use this structure's information to determine if there is still incoming data to be received from the firmware. + + @see + tpfAppEthCb + tstrEthInitParam + + @warning + Make sure that ETHERNET/bypass mode is defined before using @ref tstrM2mIpCtrlBuf + + */ +typedef struct{ + uint16 u16DataSize; + /*!< + Size of the received data in bytes. + */ + uint16 u16RemainigDataSize; + /*!< + Size of the remaining data bytes to be delivered to host. + */ +} tstrM2mIpCtrlBuf; + + +/** +@struct \ + tstrWifiInitParam + +@brief + Structure, holding the Wi-fi configuration attributes such as the wi-fi callback , monitoring mode callback and Ethernet parameter initialization structure. + Such configuration parameters are required to be set before calling the wi-fi initialization function @ref m2m_wifi_init. + @ref pfAppWifiCb attribute must be set to handle the wi-fi callback operations. + @ref pfAppMonCb attribute, is optional based on whether the application requires the monitoring mode configuration, and can there not + be set before the initialization. + @ref strEthInitParam structure, is another optional configuration based on whether the bypass mode is set. + + @see + tpfAppEthCb + tpfAppMonCb + tstrEthInitParam + +*/ +typedef struct { + tpfAppWifiCb pfAppWifiCb; + /*!< + Callback for Wi-Fi notifications. + */ + tpfAppMonCb pfAppMonCb; + /*!< + Callback for monitoring interface. + */ + tstrEthInitParam strEthInitParam ; + /*!< + Structure to hold Ethernet interface parameters. + */ + +} tstrWifiInitParam; + //@} +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +FUNCTION PROTOTYPES +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ +/** \defgroup WLANAPI Function + * @ingroup m2m_wifi + */ +#ifdef __cplusplus + extern "C" { +#endif + /** @defgroup WiFiDownloadFn m2m_wifi_download_mode + * @ingroup WLANAPI + * Synchronous download mode entry function that prepares the WINC board to enter the download mode, ready for the firmware or certificate download. +* The WINC board is prepared for download, through initializations for the WINC driver including bus initializations and interrupt enabling, it also halts the chip, to allow for the firmware downloads. +* Firmware can be downloaded through a number of interfaces, UART, I2C and SPI. + */ + /**@{*/ +/*! +@fn \ + NMI_API void m2m_wifi_download_mode(void); +@brief Prepares the WINC broard before downloading any data (Firmware, Certificates .. etc) + + This function should called before starting to download any data to the WINC board. The WINC board is prepared for download, through initializations for the WINC driver including bus initializations + and interrupt enabling, it also halts the chip, to allow for the firmware downloads Firmware can be downloaded through a number of interfaces, UART, I2C and SPI. + +@return + The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +*/ +NMI_API sint8 m2m_wifi_download_mode(void); + + /**@}*/ + /** @defgroup WifiInitFn m2m_wifi_init + * @ingroup WLANAPI + * Synchronous initialization function for the WINC driver. This function initializes the driver by, registering the call back function for M2M_WIFI layer(also the call back function for bypass mode/monitoring mode if defined), + * initializing the host interface layer and the bus interfaces. + * Wi-Fi callback registering is essential to allow the handling of the events received, in response to the asynchronous Wi-Fi operations. + +Following are the possible Wi-Fi events that are expected to be received through the call back function(provided by the application) to the M2M_WIFI layer are : + + @ref M2M_WIFI_RESP_CON_STATE_CHANGED \n + @ref M2M_WIFI_RESP_CONN_INFO \n + @ref M2M_WIFI_REQ_DHCP_CONF \n + @ref M2M_WIFI_REQ_WPS \n + @ref M2M_WIFI_RESP_IP_CONFLICT \n + @ref M2M_WIFI_RESP_SCAN_DONE \n + @ref M2M_WIFI_RESP_SCAN_RESULT \n + @ref M2M_WIFI_RESP_CURRENT_RSSI \n + @ref M2M_WIFI_RESP_CLIENT_INFO \n + @ref M2M_WIFI_RESP_PROVISION_INFO \n + @ref M2M_WIFI_RESP_DEFAULT_CONNECT \n + Example: \n + In case Bypass mode is defined : \n + @ref M2M_WIFI_RESP_ETHERNET_RX_PACKET + + In case Monitoring mode is used: \n + @ref M2M_WIFI_RESP_WIFI_RX_PACKET + + Any application using the WINC driver must call this function at the start of its main function. + */ + /**@{*/ +/*! +@fn \ + NMI_API sint8 m2m_wifi_init(tstrWifiInitParam * pWifiInitParam); + +@param [in] pWifiInitParam + This is a pointer to the @ref tstrWifiInitParam structure which holds the pointer to the application WIFI layer call back function, + monitoring mode call back and @ref tstrEthInitParam structure containing bypass mode parameters. + +@brief Initialize the WINC host driver. + This function initializes the driver by, registering the call back function for M2M_WIFI layer(also the call back function for bypass mode/monitoring mode if defined), + initializing the host interface layer and the bus interfaces. + +@pre + Prior to this function call, The application should initialize the BSP using "nm_bsp_init". + Also,application users must provide a call back function responsible for receiving all the WI-FI events that are received on the M2M_WIFI layer. + +@warning + Failure to successfully complete function indicates that the driver couldn't be initialized and a fatal error will prevent the application from proceeding. + +@see + nm_bsp_init + m2m_wifi_deinit + tenuM2mStaCmd + +@return + The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +*/ +NMI_API sint8 m2m_wifi_init(tstrWifiInitParam * pWifiInitParam); + /**@}*/ + /** @defgroup WifiDeinitFn m2m_wifi_deinit + * @ingroup WLANAPI + * Synchronous de-initialization function to the WINC1500 driver. De-initializes the host interface and frees any resources used by the M2M_WIFI layer. + * This function must be called in the application closing phase to ensure that all resources have been correctly released. No arguments are expected to be passed in. + */ +/**@{*/ +/*! +@fn \ + NMI_API sint8 m2m_wifi_deinit(void * arg); + +@param [in] arg + Generic argument. Not used in the current implementation. +@brief Deinitilize the WINC driver and host enterface. + This function must be called at the De-initilization stage of the application. Generally This function should be the last function before switching off the chip + and it should be followed only by "nm_bsp_deinit" function call. Every function call of "nm_wifi_init" should be matched with a call to nm_wifi_deinit. +@see + nm_bsp_deinit + nm_wifi_init + +@return + The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +*/ +NMI_API sint8 m2m_wifi_deinit(void * arg); + + /**@}*/ +/** @defgroup WifiHandleEventsFn m2m_wifi_handle_events +* @ingroup WLANAPI +* Synchronous M2M event handler function, responsible for handling interrupts received from the WINC firmware. +* Application developers should call this function periodically in-order to receive the events that are to be handled by the +* callback functions implemented by the application. + + */ + /**@{*/ +/*! +@fn \ + NMI_API sint8 m2m_wifi_handle_events(void * arg); + +@pre + Prior to receiving events, the WINC driver should have been successfully initialized by calling the @ref m2m_wifi_init function. + +@brief Handle the varios events received from the WINC board. + Whenever an event happen in the WINC board (e.g. Connection, Disconnection , DHCP .. etc), WINC will interrupt the host to let it know that a new + event has occured. The host driver will attempt to handle these events whenever the host driver decides to do that by calling the "m2m_wifi_handle_events" function. + It's mandatory to call this function periodically and independantly of any other condition. It's ideal to include this function in the main and the most frequent loop of the + host application. +@warning + Failure to successfully complete this function indicates bus errors and hence a fatal error that will prevent the application from proceeding. + +@return + The function returns @ref M2M_SUCCESS for successful interrupt handling and a negative value otherwise. +*/ + +NMI_API sint8 m2m_wifi_handle_events(void * arg); + + /**@}*/ +/** @defgroup WifiSendCRLFn m2m_wifi_send_crl +* @ingroup WLANAPI +* Asynchronous API that notifies the WINC with the Certificate Revocation List to be used for TLS. + + */ + /**@{*/ +/*! +@fn \ + sint8 m2m_wifi_send_crl(tstrTlsCrlInfo* pCRL); + +@brief + Asynchronous API that notifies the WINC with the Certificate Revocation List. + +@param [in] pCRL + Pointer to the structure containing certificate revocation list details. + +@return + The function returns @ref M2M_SUCCESS if the command has been successfully queued to the WINC, + and a negative value otherwise. +*/ + +sint8 m2m_wifi_send_crl(tstrTlsCrlInfo* pCRL); + + /**@}*/ +/** @defgroup WifiDefaultConnectFn m2m_wifi_default_connect + * @ingroup WLANAPI + * Asynchronous Wi-Fi connection function. An application calling this function will cause the firmware to correspondingly connect to the last successfully connected AP from the cached connections. + * A failure to connect will result in a response of @ref M2M_WIFI_RESP_DEFAULT_CONNECT indicating the connection error as defined in the structure @ref tstrM2MDefaultConnResp. + * Possible errors are: + * The connection list is empty @ref M2M_DEFAULT_CONN_EMPTY_LIST or a mismatch for the saved AP name @ref M2M_DEFAULT_CONN_SCAN_MISMATCH. + * only difference between this function and @ref m2m_wifi_connect, is the connection parameters. + * Connection using this function is expected to connect using cached connection parameters. + + */ + /**@{*/ +/*! +@fn \ + NMI_API sint8 m2m_wifi_default_connect(void); + +@pre + Prior to connecting, the WINC driver should have been successfully initialized by calling the @ref m2m_wifi_init function. + +@brief Connect to the last successfully connected AP from the cached connections. + +@warning + This function must be called in station mode only. + It's important to note that successful completion of a call to m2m_wifi_default_connect() does not guarantee success of the WIFI connection, + and a negative return value indicates only locally-detected errors. + +@see + m2m_wifi_connect + +@return + The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. + +*/ +NMI_API sint8 m2m_wifi_default_connect(void); + /**@}*/ +/** @defgroup WifiConnectFn m2m_wifi_connect + * @ingroup WLANAPI + * Asynchronous wi-fi connection function to a specific AP. Prior to a successful connection, the application must define the SSID of the AP, the security type, + * the authentication information parameters and the channel number to which the connection will be established. + * The connection status is known when a response of @ref M2M_WIFI_RESP_CON_STATE_CHANGED is received based on the states defined in @ref tenuM2mConnState, + * successful connection is defined by @ref M2M_WIFI_CONNECTED +* + * The only difference between this function and @ref m2m_wifi_default_connect, is the connection parameters. + * Connection using this function is expected to be made to a specific AP and to a specified channel. + */ + /**@{*/ +/*! +@fn \ + NMI_API sint8 m2m_wifi_connect(char *pcSsid, uint8 u8SsidLen, uint8 u8SecType, void *pvAuthInfo, uint16 u16Ch); + +@param [in] pcSsid + A buffer holding the SSID corresponding to the requested AP. + +@param [in] u8SsidLen + Length of the given SSID (not including the NULL termination). + A length less than ZERO or greater than the maximum defined SSID @ref M2M_MAX_SSID_LEN will result in a negative error + @ref M2M_ERR_FAIL. + +@param [in] u8SecType + Wi-Fi security type security for the network. It can be one of the following types: + -@ref M2M_WIFI_SEC_OPEN + -@ref M2M_WIFI_SEC_WEP + -@ref M2M_WIFI_SEC_WPA_PSK + -@ref M2M_WIFI_SEC_802_1X + A value outside these possible values will result in a negative return error @ref M2M_ERR_FAIL. + +@param [in] pvAuthInfo + Authentication parameters required for completing the connection. It is type is based on the Security type. + If the authentication parameters are NULL or are greater than the maximum length of the authentication parameters length as defined by + @ref M2M_MAX_PSK_LEN a negative error will return @ref M2M_ERR_FAIL(-12) indicating connection failure. + +@param [in] u16Ch + Wi-Fi channel number as defined in @ref tenuM2mScanCh enumeration. + Channel number greater than @ref M2M_WIFI_CH_14 returns a negative error @ref M2M_ERR_FAIL(-12). + Except if the value is M2M_WIFI_CH_ALL(255), since this indicates that the firmware should scan all channels to find the SSID requested to connect to. + Failure to find the connection match will return a negative error @ref M2M_DEFAULT_CONN_SCAN_MISMATCH. +@pre + Prior to a successful connection request, the Wi-Fi driver must have been successfully initialized through the call of the @ref @m2m_wifi_init function +@see + tuniM2MWifiAuth + tstr1xAuthCredentials + tstrM2mWifiWepParams + +@warning + -This function must be called in station mode only. + -Successful completion of this function does not guarantee success of the WIFI connection, and + a negative return value indicates only locally-detected errors. + +@return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. + +*/ +NMI_API sint8 m2m_wifi_connect(char *pcSsid, uint8 u8SsidLen, uint8 u8SecType, void *pvAuthInfo, uint16 u16Ch); + /**@}*/ +/** @defgroup WifiConnectFn m2m_wifi_connect_sc + * @ingroup WLANAPI + * Asynchronous wi-fi connection function to a specific AP. Prior to a successful connection, the application developers must know the SSID of the AP, the security type, + * the authentication information parameters and the channel number to which the connection will be established.this API allows the user to choose + * whether to + * The connection status is known when a response of @ref M2M_WIFI_RESP_CON_STATE_CHANGED is received based on the states defined in @ref tenuM2mConnState, + * successful connection is defined by @ref M2M_WIFI_CONNECTED + * The only difference between this function and @ref m2m_wifi_connect, is the option to save the acess point info ( SSID, password...etc) or not. + * Connection using this function is expected to be made to a specific AP and to a specified channel. + */ + /**@{*/ +/*! +@fn \ + NMI_API sint8 m2m_wifi_connect_sc(char *pcSsid, uint8 u8SsidLen, uint8 u8SecType, void *pvAuthInfo, uint16 u16Ch,uint8 u8SaveCred); + +@param [in] pcSsid + A buffer holding the SSID corresponding to the requested AP. + +@param [in] u8SsidLen + Length of the given SSID (not including the NULL termination). + A length less than ZERO or greater than the maximum defined SSID @ref M2M_MAX_SSID_LEN will result in a negative error + @ref M2M_ERR_FAIL. + +@param [in] u8SecType + Wi-Fi security type security for the network. It can be one of the following types: + -@ref M2M_WIFI_SEC_OPEN + -@ref M2M_WIFI_SEC_WEP + -@ref M2M_WIFI_SEC_WPA_PSK + -@ref M2M_WIFI_SEC_802_1X + A value outside these possible values will result in a negative return error @ref M2M_ERR_FAIL. + +@param [in] pvAuthInfo + Authentication parameters required for completing the connection. It is type is based on the Security type. + If the authentication parameters are NULL or are greater than the maximum length of the authentication parameters length as defined by + @ref M2M_MAX_PSK_LEN a negative error will return @ref M2M_ERR_FAIL(-12) indicating connection failure. + +@param [in] u16Ch + Wi-Fi channel number as defined in @ref tenuM2mScanCh enumeration. + Channel number greater than @ref M2M_WIFI_CH_14 returns a negative error @ref M2M_ERR_FAIL(-12). + Except if the value is M2M_WIFI_CH_ALL(255), since this indicates that the firmware should scan all channels to find the SSID requested to connect to. + Failure to find the connection match will return a negative error @ref M2M_DEFAULT_CONN_SCAN_MISMATCH. + +@param [in] u8NoSaveCred + Option to store the acess point SSID and password into the WINC flash memory or not. + +@pre + Prior to a successful connection request, the wi-fi driver must have been successfully initialized through the call of the @ref @m2m_wifi_init function +@see + tuniM2MWifiAuth + tstr1xAuthCredentials + tstrM2mWifiWepParams + +@warning + -This function must be called in station mode only. + -Successful completion of this function does not guarantee success of the WIFI connection, and + a negative return value indicates only locally-detected errors. + +@return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. + +*/ + NMI_API sint8 m2m_wifi_connect_sc(char *pcSsid, uint8 u8SsidLen, uint8 u8SecType, void *pvAuthInfo, uint16 u16Ch, uint8 u8SaveCred); + /**@}*/ +/** @defgroup WifiDisconnectFn m2m_wifi_disconnect + * @ingroup WLANAPI + * Synchronous wi-fi disconnection function, requesting a Wi-Fi disconnection from the currently connected AP. + */ + /**@{*/ +/*! +@fn \ + NMI_API sint8 m2m_wifi_disconnect(void); + +@pre + Disconnection request must be made to a successfully connected AP. If the WINC is not in the connected state, a call to this function will hold insignificant. + +@brief Request a Wi-Fi disconnect from the currently connected AP. + After the Disconnect is complete the driver should recieve a response of @ref M2M_WIFI_RESP_CON_STATE_CHANGED based on the states defined + in @ref tenuM2mConnState, successful disconnection is defined by @ref M2M_WIFI_DISCONNECTED . +@warning + This function must be called in station mode only. + +@see + m2m_wifi_connect + m2m_wifi_default_connect + +@return + The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +*/ +NMI_API sint8 m2m_wifi_disconnect(void); + + /**@}*/ +/** @defgroup StartProvisionModeFn m2m_wifi_start_provision_mode + * @ingroup WLANAPI + * Asynchronous Wi-Fi provisioning function, which starts the WINC HTTP PROVISIONING mode. + The function triggers the WINC to activate the Wi-Fi AP (HOTSPOT) mode with the passed configuration parameters and then starts the + HTTP Provision WEB Server. + The provisioning status is returned in an event @ref M2M_WIFI_RESP_PROVISION_INFO + */ + /**@{*/ +/*! +@fn \ + NMI_API sint8 m2m_wifi_start_provision_mode(tstrM2MAPConfig *pstrAPConfig, char *pcHttpServerDomainName, uint8 bEnableHttpRedirect); + +@param [in] pstrAPConfig + AP configuration parameters as defined in @ref tstrM2MAPConfig configuration structure. + A NULL value passed in, will result in a negative error @ref M2M_ERR_FAIL. + +@param [in] pcHttpServerDomainName + Domain name of the HTTP Provision WEB server which others will use to load the provisioning Home page. + The domain name can have one of the following 3 forms: + 1- "wincprov.com" + 2- "http://wincprov.com" + 3- "https://wincprov.com" + The forms 1 and 2 are equivalent, they both will start a plain http server, while form 3 + will start a secure HTTP provisioning Session (HTTP over SSL connection). + +@param [in] bEnableHttpRedirect + A flag to enable/disable the HTTP redirect feature. If Secure provisioning is enabled (i.e. the server + domain name uses "https" prefix) this flag is ignored (no meaning for redirect in HTTPS). + Possible values are: + - ZERO DO NOT Use HTTP Redirect. In this case the associated device could open the provisioning page ONLY when + the HTTP Provision URL of the WINC HTTP Server is correctly written on the browser. + - Non-Zero value Use HTTP Redirect. In this case, all http traffic (http://URL) from the associated + device (Phone, PC, ...etc) will be redirected to the WINC HTTP Provisioning Home page. + +@pre + - A Wi-Fi notification callback of type @ref tpfAppWifiCb MUST be implemented and registered at startup. Registering the callback + is done through passing it to the initialization @ref m2m_wifi_init function. + - The event @ref M2M_WIFI_RESP_CONN_INFO must be handled in the callback to receive the requested connection info. + +@see + tpfAppWifiCb + m2m_wifi_init + M2M_WIFI_RESP_PROVISION_INFO + m2m_wifi_stop_provision_mode + tstrM2MAPConfig + +@warning + DO Not use ".local" in the pcHttpServerDomainName. + +@return + The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. + +\section Example + The example demonstrates a code snippet for how provisioning is triggered and the response event received accordingly. +@code + #include "m2m_wifi.h" + #include "m2m_types.h" + + + void wifi_event_cb(uint8 u8WiFiEvent, void * pvMsg) + { + switch(u8WiFiEvent) + { + case M2M_WIFI_RESP_PROVISION_INFO: + { + tstrM2MProvisionInfo *pstrProvInfo = (tstrM2MProvisionInfo*)pvMsg; + if(pstrProvInfo->u8Status == M2M_SUCCESS) + { + m2m_wifi_connect((char*)pstrProvInfo->au8SSID, (uint8)strlen(pstrProvInfo->au8SSID), pstrProvInfo->u8SecType, + pstrProvInfo->au8Password, M2M_WIFI_CH_ALL); + + printf("PROV SSID : %s\n",pstrProvInfo->au8SSID); + printf("PROV PSK : %s\n",pstrProvInfo->au8Password); + } + else + { + printf("(ERR) Provisioning Failed\n"); + } + } + break; + + default: + break; + } + } + + int main() + { + tstrWifiInitParam param; + + param.pfAppWifiCb = wifi_event_cb; + if(!m2m_wifi_init(¶m)) + { + tstrM2MAPConfig apConfig; + uint8 bEnableRedirect = 1; + + strcpy(apConfig.au8SSID, "WINC_SSID"); + apConfig.u8ListenChannel = 1; + apConfig.u8SecType = M2M_WIFI_SEC_OPEN; + apConfig.u8SsidHide = 0; + + // IP Address + apConfig.au8DHCPServerIP[0] = 192; + apConfig.au8DHCPServerIP[1] = 168; + apConfig.au8DHCPServerIP[2] = 1; + apConfig.au8DHCPServerIP[0] = 1; + + m2m_wifi_start_provision_mode(&apConfig, "atmelwincconf.com", bEnableRedirect); + + while(1) + { + m2m_wifi_handle_events(NULL); + } + } + } + +@endcode +*/ +NMI_API sint8 m2m_wifi_start_provision_mode(tstrM2MAPConfig *pstrAPConfig, char *pcHttpServerDomainName, uint8 bEnableHttpRedirect); + /**@}*/ +/** @defgroup StopProvisioningModeFn m2m_wifi_stop_provision_mode + * @ingroup WLANAPI + * Synchronous provision termination function which stops the provision mode if it is active. + */ + /**@{*/ +/*! +@fn \ + sint8 m2m_wifi_stop_provision_mode(void); + +@pre + An active provisioning session must be active before it is terminated through this function. +@see + m2m_wifi_start_provision_mode + +@return + The function returns ZERO for success and a negative value otherwise. +*/ +NMI_API sint8 m2m_wifi_stop_provision_mode(void); + /**@}*/ +/** @defgroup GetConnectionInfoFn m2m_wifi_get_connection_info + * @ingroup WLANAPI + * Asynchronous connection status retrieval function, retrieves the status information of the currently connected AP. The result is passed to the Wi-Fi notification callback +* through the event @ref M2M_WIFI_RESP_CONN_INFO. Connection information is retrieved from the structure @ref tstrM2MConnInfo. + */ + /**@{*/ +/*! +@fn \ + sint8 m2m_wifi_get_connection_info(void); + +@brief + Retrieve the current Connection information. The result is passed to the Wi-Fi notification callback + with [M2M_WIFI_RESP_CONN_INFO](@ref M2M_WIFI_RESP_CONN_INFO). +@pre + - A Wi-Fi notification callback of type @ref tpfAppWifiCb MUST be implemented and registered at startup. Registering the callback + is done through passing it to the initialization @ref m2m_wifi_init function. + - The event @ref M2M_WIFI_RESP_CONN_INFO must be handled in the callback to receive the requested connection info. + + Connection Information retrieved: + + + -Connection Security + -Connection RSSI + -Remote MAC address + -Remote IP address + + and in case of WINC station mode the SSID of the AP is also retrieved. +@warning + -In case of WINC AP mode or P2P mode, ignore the SSID field (NULL string). +@sa + M2M_WIFI_RESP_CONN_INFO, + tstrM2MConnInfo +@return + The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +\section Example + The code snippet shows an example of how wi-fi connection information is retrieved . +@code + + #include "m2m_wifi.h" + #include "m2m_types.h" + + + void wifi_event_cb(uint8 u8WiFiEvent, void * pvMsg) + { + switch(u8WiFiEvent) + { + case M2M_WIFI_RESP_CONN_INFO: + { + tstrM2MConnInfo *pstrConnInfo = (tstrM2MConnInfo*)pvMsg; + + printf("CONNECTED AP INFO\n"); + printf("SSID : %s\n",pstrConnInfo->acSSID); + printf("SEC TYPE : %d\n",pstrConnInfo->u8SecType); + printf("Signal Strength : %d\n", pstrConnInfo->s8RSSI); + printf("Local IP Address : %d.%d.%d.%d\n", + pstrConnInfo->au8IPAddr[0] , pstrConnInfo->au8IPAddr[1], pstrConnInfo->au8IPAddr[2], pstrConnInfo->au8IPAddr[3]); + } + break; + + case M2M_WIFI_REQ_DHCP_CONF: + { + // Get the current AP information. + m2m_wifi_get_connection_info(); + } + break; + default: + break; + } + } + + int main() + { + tstrWifiInitParam param; + + param.pfAppWifiCb = wifi_event_cb; + if(!m2m_wifi_init(¶m)) + { + // connect to the default AP + m2m_wifi_default_connect(); + + while(1) + { + m2m_wifi_handle_events(NULL); + } + } + } + +@endcode +*/ +NMI_API sint8 m2m_wifi_get_connection_info(void); + /**@}*/ +/** @defgroup WifiSetMacAddFn m2m_wifi_set_mac_address + * @ingroup WLANAPI + * Synchronous MAC address assigning to the NMC1500. It is used for non-production SW. Assign MAC address to the WINC device. + */ + /**@{*/ +/*! +@fn \ + NMI_API sint8 m2m_wifi_set_mac_address(uint8 au8MacAddress[6]); + +@brief Assign a MAC address to the WINC board. + This function override the already assigned MAC address of the WINC board with a user provided one. This is for experimental + use only and should never be used in the production SW. + +@param [in] au8MacAddress + MAC Address to be set to the WINC. + +@return + The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +*/ +NMI_API sint8 m2m_wifi_set_mac_address(uint8 au8MacAddress[6]); + + /**@}*/ +/** @defgroup WifiWpsFn m2m_wifi_wps + * @ingroup WLANAPI + * Asynchronous WPS triggering function. + * This function is called for the WINC to enter the WPS (Wi-Fi Protected Setup) mode. The result is passed to the Wi-Fi notification callback +* with the event @ref M2M_WIFI_REQ_WPS. + */ + /**@{*/ +/*! +@fn \ + NMI_API sint8 m2m_wifi_wps(uint8 u8TriggerType,const char * pcPinNumber); + +@param [in] u8TriggerType + WPS Trigger method. Could be: + - [WPS_PIN_TRIGGER](@ref WPS_PIN_TRIGGER) Push button method + - [WPS_PBC_TRIGGER](@ref WPS_PBC_TRIGGER) Pin method + +@param [in] pcPinNumber + PIN number for WPS PIN method. It is not used if the trigger type is WPS_PBC_TRIGGER. It must follow the rules + stated by the WPS standard. + +@warning + This function is not allowed in AP or P2P modes. + +@pre + - A Wi-Fi notification callback of type (@ref tpfAppWifiCb MUST be implemented and registered at startup. Registering the callback + is done through passing it to the [m2m_wifi_init](@ref m2m_wifi_init). + - The event [M2M_WIFI_REQ_WPS](@ref M2M_WIFI_REQ_WPS) must be handled in the callback to receive the WPS status. + - The WINC device MUST be in IDLE or STA mode. If AP or P2P mode is active, the WPS will not be performed. + - The [m2m_wifi_handle_events](@ref m2m_wifi_handle_events) MUST be called periodically to receive the responses in the callback. +@see + tpfAppWifiCb + m2m_wifi_init + M2M_WIFI_REQ_WPS + tenuWPSTrigger + tstrM2MWPSInfo + +@return + The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +\section Example + The code snippet shows an example of how Wi-Fi WPS is triggered . +@code + + #include "m2m_wifi.h" + #include "m2m_types.h" + + void wifi_event_cb(uint8 u8WiFiEvent, void * pvMsg) + { + switch(u8WiFiEvent) + { + case M2M_WIFI_REQ_WPS: + { + tstrM2MWPSInfo *pstrWPS = (tstrM2MWPSInfo*)pvMsg; + if(pstrWPS->u8AuthType != 0) + { + printf("WPS SSID : %s\n",pstrWPS->au8SSID); + printf("WPS PSK : %s\n",pstrWPS->au8PSK); + printf("WPS SSID Auth Type : %s\n",pstrWPS->u8AuthType == M2M_WIFI_SEC_OPEN ? "OPEN" : "WPA/WPA2"); + printf("WPS Channel : %d\n",pstrWPS->u8Ch + 1); + + // establish Wi-Fi connection + m2m_wifi_connect((char*)pstrWPS->au8SSID, (uint8)m2m_strlen(pstrWPS->au8SSID), + pstrWPS->u8AuthType, pstrWPS->au8PSK, pstrWPS->u8Ch); + } + else + { + printf("(ERR) WPS Is not enabled OR Timed out\n"); + } + } + break; + + default: + break; + } + } + + int main() + { + tstrWifiInitParam param; + + param.pfAppWifiCb = wifi_event_cb; + if(!m2m_wifi_init(¶m)) + { + // Trigger WPS in Push button mode. + m2m_wifi_wps(WPS_PBC_TRIGGER, NULL); + + while(1) + { + m2m_wifi_handle_events(NULL); + } + } + } + +@endcode +*/ +NMI_API sint8 m2m_wifi_wps(uint8 u8TriggerType,const char *pcPinNumber); + /**@}*/ +/** @defgroup WifiWpsDisableFn m2m_wifi_wps_disable + * @ingroup WLANAPI + * Disable the WINC1500 WPS operation. + */ + /**@{*/ +/*! +@fn \ + NMI_API sint8 m2m_wifi_wps_disable(void); + +@pre WINC should be already in WPS mode using @ref m2m_wifi_wps + +@brief Stops the WPS ongoing session. + +@see + m2m_wifi_wps + +@return + The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +*/ +NMI_API sint8 m2m_wifi_wps_disable(void); + + /**@}*/ +/** @defgroup WifiP2PFn m2m_wifi_p2p + * @ingroup WLANAPI + * Asynchronous Wi-Fi direct (P2P) enabling mode function. + The WINC supports P2P in device listening mode ONLY (intent is ZERO). + The WINC P2P implementation does not support P2P GO (Group Owner) mode. + Active P2P devices (e.g. phones) could find the WINC in the search list. When a device is connected to WINC, a Wi-Fi notification event + @ref M2M_WIFI_RESP_CON_STATE_CHANGED is triggered. After a short while, the DHCP IP Address is obtained + and an event @ref M2M_WIFI_REQ_DHCP_CONF is triggered. Refer to the code examples for a more illustrative example. + */ + /**@{*/ +/*! +@fn \ + NMI_API sint8 m2m_wifi_p2p(uint8 u8Channel); + +@param [in] u8Channel + P2P Listen RF channel. According to the P2P standard It must hold only one of the following values 1, 6 or 11. + +@pre + - A Wi-Fi notification callback of type @ref tpfAppWifiCb MUST be implemented and registered at initialization. Registering the callback + is done through passing it to the @ref m2m_wifi_init. + - The events @ref M2M_WIFI_RESP_CON_STATE_CHANGED and @ref M2M_WIFI_REQ_DHCP_CONF + must be handled in the callback. + - The @ref m2m_wifi_handle_events MUST be called to receive the responses in the callback. + +@warning + This function is not allowed in AP or STA modes. + +@see + tpfAppWifiCb + m2m_wifi_init + M2M_WIFI_RESP_CON_STATE_CHANGED + M2M_WIFI_REQ_DHCP_CONF + tstrM2mWifiStateChanged + +@return + The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +\section Example + The code snippet shown an example of how the p2p mode operates. +@code + #include "m2m_wifi.h" + #include "m2m_types.h" + + void wifi_event_cb(uint8 u8WiFiEvent, void * pvMsg) + { + switch(u8WiFiEvent) + { + case M2M_WIFI_RESP_CON_STATE_CHANGED: + { + tstrM2mWifiStateChanged *pstrWifiState = (tstrM2mWifiStateChanged*)pvMsg; + M2M_INFO("Wifi State :: %s :: ErrCode %d\n", pstrWifiState->u8CurrState? "CONNECTED":"DISCONNECTED",pstrWifiState->u8ErrCode); + + // Do something + } + break; + + case M2M_WIFI_REQ_DHCP_CONF: + { + uint8 *pu8IPAddress = (uint8*)pvMsg; + + printf("P2P IP Address \"%u.%u.%u.%u\"\n",pu8IPAddress[0],pu8IPAddress[1],pu8IPAddress[2],pu8IPAddress[3]); + } + break; + + default: + break; + } + } + + int main() + { + tstrWifiInitParam param; + + param.pfAppWifiCb = wifi_event_cb; + if(!m2m_wifi_init(¶m)) + { + // Trigger P2P + m2m_wifi_p2p(M2M_WIFI_CH_1); + + while(1) + { + m2m_wifi_handle_events(NULL); + } + } + } + +@endcode + +*/ +NMI_API sint8 m2m_wifi_p2p(uint8 u8Channel); + /**@}*/ +/** @defgroup WifiP2PDisconnectFn m2m_wifi_p2p_disconnect + * @ingroup WLANAPI + * Disable the WINC1500 device Wi-Fi direct mode (P2P). + */ + /**@{*/ +/*! +@fn \ + NMI_API sint8 m2m_wifi_p2p_disconnect(void); +@pre + The p2p mode must have be enabled and active before a disconnect can be called. + +@see + m2m_wifi_p2p +@return + The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +*/ +NMI_API sint8 m2m_wifi_p2p_disconnect(void); + /**@}*/ +/** @defgroup WifiEnableApFn m2m_wifi_enable_ap + * @ingroup WLANAPI + * Asynchronous Wi-FI hot-spot enabling function. + * The WINC supports AP mode operation with the following limitations: + - Only 1 STA could be associated at a time. + - Open and WEP are the only supported security types + */ + /**@{*/ +/*! +@fn \ + NMI_API sint8 m2m_wifi_enable_ap(CONST tstrM2MAPConfig* pstrM2MAPConfig); + +@param [in] pstrM2MAPConfig + A structure holding the AP configurations. + +@warning + This function is not allowed in P2P or STA modes. + +@pre + - A Wi-Fi notification callback of type @ref tpfAppWifiCb MUST be implemented and registered at initialization. Registering the callback + is done through passing it to the [m2m_wifi_init](@ref m2m_wifi_init). + - The event @ref M2M_WIFI_REQ_DHCP_CONF must be handled in the callback. + - The @ref m2m_wifi_handle_events MUST be called to receive the responses in the callback. + +@see + tpfAppWifiCb + tenuM2mSecType + m2m_wifi_init + M2M_WIFI_REQ_DHCP_CONF + tstrM2mWifiStateChanged + tstrM2MAPConfig + +@return + The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +\section Example + The code snippet demonstrates how the AP mode is enabled after the driver is initialized in the application's main function and the handling + of the event @ref M2M_WIFI_REQ_DHCP_CONF, to indicate successful connection. +@code + #include "m2m_wifi.h" + #include "m2m_types.h" + + void wifi_event_cb(uint8 u8WiFiEvent, void * pvMsg) + { + switch(u8WiFiEvent) + { + case M2M_WIFI_REQ_DHCP_CONF: + { + uint8 *pu8IPAddress = (uint8*)pvMsg; + + printf("Associated STA has IP Address \"%u.%u.%u.%u\"\n",pu8IPAddress[0],pu8IPAddress[1],pu8IPAddress[2],pu8IPAddress[3]); + } + break; + + default: + break; + } + } + + int main() + { + tstrWifiInitParam param; + + param.pfAppWifiCb = wifi_event_cb; + if(!m2m_wifi_init(¶m)) + { + tstrM2MAPConfig apConfig; + + strcpy(apConfig.au8SSID, "WINC_SSID"); + apConfig.u8ListenChannel = 1; + apConfig.u8SecType = M2M_WIFI_SEC_OPEN; + apConfig.u8SsidHide = 0; + + // IP Address + apConfig.au8DHCPServerIP[0] = 192; + apConfig.au8DHCPServerIP[1] = 168; + apConfig.au8DHCPServerIP[2] = 1; + apConfig.au8DHCPServerIP[0] = 1; + + // Trigger AP + m2m_wifi_enable_ap(&apConfig); + + while(1) + { + m2m_wifi_handle_events(NULL); + } + } + } + +@endcode + +*/ +NMI_API sint8 m2m_wifi_enable_ap(CONST tstrM2MAPConfig* pstrM2MAPConfig); + /**@}*/ +/** @defgroup WifiDisableApFn m2m_wifi_disable_ap + * @ingroup WLANAPI + * Synchronous Wi-Fi hot-spot disabling function. Must be called only when the AP is enabled through the @ref m2m_wifi_enable_ap + * function. Otherwise the call to this function will not be useful. + */ + /**@{*/ +/*! +@fn \ + NMI_API sint8 m2m_wifi_disable_ap(void); +@see + m2m_wifi_enable_ap +@return + The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +*/ +NMI_API sint8 m2m_wifi_disable_ap(void); + /**@}*/ +/** @defgroup SetStaticIPFn m2m_wifi_set_static_ip + * @ingroup WLANAPI + * Synchronous static IP Address configuration function. + */ + /**@{*/ +/*! +@fn \ + NMI_API sint8 m2m_wifi_set_static_ip(tstrM2MIPConfig * pstrStaticIPConf); + +@param [in] pstrStaticIPConf + Pointer to a structure holding the static IP Configurations (IP, + Gateway, subnet mask and DNS address). + +@pre The application must disable auto DHCP using @ref m2m_wifi_enable_dhcp before assigning a static IP address. + +@brief Assign a static IP address to the WINC board. + This function assigns a static IP address in case the AP doesn't have a DHCP server or in case the application wants to assign + a predefined known IP address. The user must take in mind that assigning a static IP address might result in an IP address + conflict. In case of an IP address conflict observed by the WINC board the user will get a response of @ref M2M_WIFI_RESP_IP_CONFLICT + in the wifi callback. The application is then responsible to either solve the conflict or assign another IP address. +@warning + Normally this function normally should not be used. DHCP configuration is requested automatically after successful Wi-Fi connection is established. + +@see + tstrM2MIPConfig + + +@return + The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +*/ +NMI_API sint8 m2m_wifi_set_static_ip(tstrM2MIPConfig * pstrStaticIPConf); + + /**@}*/ +/** @defgroup RequestDHCPClientFn m2m_wifi_request_dhcp_client + * @ingroup WLANAPI + * Starts the DHCP client operation(DHCP requested by the firmware automatically in STA/AP/P2P mode). + * + */ + /**@{*/ +/*! +@fn \ + NMI_API sint8 m2m_wifi_request_dhcp_client(void); + +@warning + This function is legacy and exists only for compatability with older applications. DHCP configuration is requested automatically after successful Wi-Fi connection is established. + +@return + The function returns @ref M2M_SUCCESS always. +*/ +NMI_API sint8 m2m_wifi_request_dhcp_client(void); + /**@}*/ +/** @defgroup RequestDHCPServerFn m2m_wifi_request_dhcp_server + * @ingroup WLANAPI + * Dhcp requested by the firmware automatically in STA/AP/P2P mode). + */ + /**@{*/ +/*! +@fn \ + NMI_API sint8 m2m_wifi_request_dhcp_server(uint8* addr); + +@warning + This function is legacy and exists only for compatability with older applications. DHCP server is started automatically when enabling the AP mode. + + +@return + The function returns @ref M2M_SUCCESS always. +*/ +NMI_API sint8 m2m_wifi_request_dhcp_server(uint8* addr); + /**@}*/ +/** @defgroup WifiDHCPEnableFn m2m_wifi_enable_dhcp + * @ingroup WLANAPI + * Synchronous Wi-Fi DHCP enable function. This function Enable/Disable DHCP protocol. + */ + /**@{*/ +/*! +@fn \ + NMI_API sint8 m2m_wifi_enable_dhcp(uint8 u8DhcpEn ); + +@brief + Enable/Disable the DHCP client after connection. + +@param [in] u8DhcpEn + Possible values: + 1: Enable DHCP client after connection. + 0: Disable DHCP client after connection. +@warnings + -DHCP client is enabled by default + -This Function should be called before using m2m_wifi_set_static_ip() + + +@sa + m2m_wifi_set_static_ip() + +@return + The function SHALL return @ref M2M_SUCCESS for successful operation and a negative value otherwise. +*/ +NMI_API sint8 m2m_wifi_enable_dhcp(uint8 u8DhcpEn ); + /**@}*/ +/** @defgroup WifiSetScanOptionFn m2m_wifi_set_scan_options + * @ingroup WLANAPI + * Synchronous Wi-Fi scan settings function. This function sets the time configuration parameters for the scan operation. + */ + +/*! +@fn \ + sint8 m2m_wifi_set_scan_options(tstrM2MScanOption* ptstrM2MScanOption) + +@param [in] ptstrM2MScanOption; + Pointer to the structure holding the Scan Parameters. + +@see + tenuM2mScanCh + m2m_wifi_request_scan + tstrM2MScanOption + +@return + The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +*/ +NMI_API sint8 m2m_wifi_set_scan_options(tstrM2MScanOption* ptstrM2MScanOption); + /**@}*/ +/** @defgroup WifiSetScanRegionFn m2m_wifi_set_scan_region + * @ingroup WLANAPI + * Synchronous wi-fi scan region setting function. + * This function sets the scan region, which will affect the range of possible scan channels. + * For 2.5GHz supported in the current release, the requested scan region can't exceed the maximum number of channels (14). + *@{*/ +/*! +@fn \ + sint8 m2m_wifi_set_scan_region(uint16 ScanRegion) + +@param [in] ScanRegion; + ASIA + NORTH_AMERICA +@see + tenuM2mScanCh + m2m_wifi_request_scan + +@return + The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. + +*/ +NMI_API sint8 m2m_wifi_set_scan_region(uint16 ScanRegion); + /**@}*/ +/** @defgroup WifiRequestScanFn m2m_wifi_request_scan +* @ingroup WLANAPI +* Asynchronous Wi-FI scan request on the given channel. The scan status is delivered in the wifi event callback and then the application +* is supposed to read the scan results sequentially. +* The number of APs found (N) is returned in event @ref M2M_WIFI_RESP_SCAN_DONE with the number of found +* APs. +* The application reads the list of APs by calling the function @ref m2m_wifi_req_scan_result N times. +* +*@{*/ +/*! +@fn \ + NMI_API sint8 m2m_wifi_request_scan(uint8 ch); + +@param [in] ch + RF Channel ID for SCAN operation. It should be set according to tenuM2mScanCh. + With a value of M2M_WIFI_CH_ALL(255)), means to scan all channels. + +@warning + This function is not allowed in P2P or AP modes. It works only for STA mode (both connected or disconnected states). + +@pre + - A Wi-Fi notification callback of type @ref tpfAppWifiCb MUST be implemented and registered at initialization. Registering the callback + is done through passing it to the @ref m2m_wifi_init. + - The events @ref M2M_WIFI_RESP_SCAN_DONE and @ref M2M_WIFI_RESP_SCAN_RESULT. + must be handled in the callback. + - The @ref m2m_wifi_handle_events function MUST be called to receive the responses in the callback. + +@see + M2M_WIFI_RESP_SCAN_DONE + M2M_WIFI_RESP_SCAN_RESULT + tpfAppWifiCb + tstrM2mWifiscanResult + tenuM2mScanCh + m2m_wifi_init + m2m_wifi_handle_events + m2m_wifi_req_scan_result + +@return + The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +\section Example + The code snippet demonstrates an example of how the scan request is called from the application's main function and the handling of + the events received in response. +@code + + #include "m2m_wifi.h" + #include "m2m_types.h" + + void wifi_event_cb(uint8 u8WiFiEvent, void * pvMsg) + { + static uint8 u8ScanResultIdx = 0; + + switch(u8WiFiEvent) + { + case M2M_WIFI_RESP_SCAN_DONE: + { + tstrM2mScanDone *pstrInfo = (tstrM2mScanDone*)pvMsg; + + printf("Num of AP found %d\n",pstrInfo->u8NumofCh); + if(pstrInfo->s8ScanState == M2M_SUCCESS) + { + u8ScanResultIdx = 0; + if(pstrInfo->u8NumofCh >= 1) + { + m2m_wifi_req_scan_result(u8ScanResultIdx); + u8ScanResultIdx ++; + } + else + { + printf("No AP Found Rescan\n"); + m2m_wifi_request_scan(M2M_WIFI_CH_ALL); + } + } + else + { + printf("(ERR) Scan fail with error <%d>\n",pstrInfo->s8ScanState); + } + } + break; + + case M2M_WIFI_RESP_SCAN_RESULT: + { + tstrM2mWifiscanResult *pstrScanResult =(tstrM2mWifiscanResult*)pvMsg; + uint8 u8NumFoundAPs = m2m_wifi_get_num_ap_found(); + + printf(">>%02d RI %d SEC %s CH %02d BSSID %02X:%02X:%02X:%02X:%02X:%02X SSID %s\n", + pstrScanResult->u8index,pstrScanResult->s8rssi, + pstrScanResult->u8AuthType, + pstrScanResult->u8ch, + pstrScanResult->au8BSSID[0], pstrScanResult->au8BSSID[1], pstrScanResult->au8BSSID[2], + pstrScanResult->au8BSSID[3], pstrScanResult->au8BSSID[4], pstrScanResult->au8BSSID[5], + pstrScanResult->au8SSID); + + if(u8ScanResultIdx < u8NumFoundAPs) + { + // Read the next scan result + m2m_wifi_req_scan_result(index); + u8ScanResultIdx ++; + } + } + break; + default: + break; + } + } + + int main() + { + tstrWifiInitParam param; + + param.pfAppWifiCb = wifi_event_cb; + if(!m2m_wifi_init(¶m)) + { + // Scan all channels + m2m_wifi_request_scan(M2M_WIFI_CH_ALL); + + while(1) + { + m2m_wifi_handle_events(NULL); + } + } + } + +@endcode +*/ +NMI_API sint8 m2m_wifi_request_scan(uint8 ch); + + /**@}*/ +/** @defgroup WifiRequestScanFn m2m_wifi_request_scan_passive +* @ingroup WLANAPI +* Same as m2m_wifi_request_scan but perform passive scanning while the other one perform active scanning. + +* +*@{*/ +/*! +@fn \ + NMI_API sint8 m2m_wifi_request_scan_passive(uint8 ch, uint16 scan_time); + +@param [in] ch + RF Channel ID for SCAN operation. It should be set according to tenuM2mScanCh. + With a value of M2M_WIFI_CH_ALL(255)), means to scan all channels. + +@param [in] scan_time + The time in ms that passive scan is listening to beacons on each channel per one slot, enter 0 for deafult setting. + +@warning + This function is not allowed in P2P or AP modes. It works only for STA mode (both connected or disconnected states). + +@pre + - A Wi-Fi notification callback of type @ref tpfAppWifiCb MUST be implemented and registered at initialization. Registering the callback + is done through passing it to the @ref m2m_wifi_init. + - The events @ref M2M_WIFI_RESP_SCAN_DONE and @ref M2M_WIFI_RESP_SCAN_RESULT. + must be handled in the callback. + - The @ref m2m_wifi_handle_events function MUST be called to receive the responses in the callback. + +@see + m2m_wifi_request_scan + M2M_WIFI_RESP_SCAN_DONE + M2M_WIFI_RESP_SCAN_RESULT + tpfAppWifiCb + tstrM2mWifiscanResult + tenuM2mScanCh + m2m_wifi_init + m2m_wifi_handle_events + m2m_wifi_req_scan_result + +@return + The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. + +*/ +NMI_API sint8 m2m_wifi_request_scan_passive(uint8 ch, uint16 scan_time); + + + /**@}*/ +/** @defgroup WifiRequestScanFn m2m_wifi_request_scan_ssid_list +* @ingroup WLANAPI +* Asynchronous wi-fi scan request on the given channel and the hidden scan list. The scan status is delivered in the wi-fi event callback and then the application +* is to read the scan results sequentially. +* The number of APs found (N) is returned in event @ref M2M_WIFI_RESP_SCAN_DONE with the number of found +* APs. +* The application could read the list of APs by calling the function @ref m2m_wifi_req_scan_result N times. +* +*@{*/ +/*! +@fn \ + NMI_API sint8 m2m_wifi_request_scan_ssid_list(uint8 ch,uint8 * u8SsidList); + +@param [in] ch + RF Channel ID for SCAN operation. It should be set according to tenuM2mScanCh. + With a value of M2M_WIFI_CH_ALL(255)), means to scan all channels. +@param [in] u8SsidList + u8SsidList is a buffer containing a list of hidden SSIDs to + include during the scan. The first byte in the buffer, u8SsidList[0], + is the number of SSIDs encoded in the string. The number of hidden SSIDs + cannot exceed MAX_HIDDEN_SITES. All SSIDs are concatenated in the following + bytes and each SSID is prefixed with a one-byte header containing its length. + The total number of bytes in u8SsidList buffer, including length byte, cannot + exceed 133 bytes (MAX_HIDDEN_SITES SSIDs x 32 bytes each, which is max SSID length). + For instance, encoding the two hidden SSIDs "DEMO_AP" and "TEST" + results in the following buffer content: +@code + uint8 u8SsidList[14]; + u8SsidList[0] = 2; // Number of SSIDs is 2 + u8SsidList[1] = 7; // Length of the string "DEMO_AP" without NULL termination + memcpy(&u8SsidList[2], "DEMO_AP", 7); // Bytes index 2-9 containing the string DEMO_AP + u8SsidList[9] = 4; // Length of the string "TEST" without NULL termination + memcpy(&u8SsidList[10], "TEST", 4); // Bytes index 10-13 containing the string TEST +@endcode + +@warning + This function is not allowed in P2P. It works only for STA/AP mode (connected or disconnected). + +@pre + - A Wi-Fi notification callback of type @ref tpfAppWifiCb MUST be implemented and registered at initialization. Registering the callback + is done through passing it to the @ref m2m_wifi_init. + - The events @ref M2M_WIFI_RESP_SCAN_DONE and @ref M2M_WIFI_RESP_SCAN_RESULT. + must be handled in the callback. + - The @ref m2m_wifi_handle_events function MUST be called to receive the responses in the callback. + +@see + M2M_WIFI_RESP_SCAN_DONE + M2M_WIFI_RESP_SCAN_RESULT + tpfAppWifiCb + tstrM2mWifiscanResult + tenuM2mScanCh + m2m_wifi_init + m2m_wifi_handle_events + m2m_wifi_req_scan_result + +@return + The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +\section Example + The code snippet demonstrates an example of how the scan request is called from the application's main function and the handling of + the events received in response. +@code + + #include "m2m_wifi.h" + #include "m2m_types.h" + + static void request_scan_hidden_demo_ap(void); + + void wifi_event_cb(uint8 u8WiFiEvent, void * pvMsg) + { + static uint8 u8ScanResultIdx = 0; + + switch(u8WiFiEvent) + { + case M2M_WIFI_RESP_SCAN_DONE: + { + tstrM2mScanDone *pstrInfo = (tstrM2mScanDone*)pvMsg; + + printf("Num of AP found %d\n",pstrInfo->u8NumofCh); + if(pstrInfo->s8ScanState == M2M_SUCCESS) + { + u8ScanResultIdx = 0; + if(pstrInfo->u8NumofCh >= 1) + { + m2m_wifi_req_scan_result(u8ScanResultIdx); + u8ScanResultIdx ++; + } + else + { + printf("No AP Found Rescan\n"); + request_scan_hidden_demo_ap(); + } + } + else + { + printf("(ERR) Scan fail with error <%d>\n",pstrInfo->s8ScanState); + } + } + break; + + case M2M_WIFI_RESP_SCAN_RESULT: + { + tstrM2mWifiscanResult *pstrScanResult =(tstrM2mWifiscanResult*)pvMsg; + uint8 u8NumFoundAPs = m2m_wifi_get_num_ap_found(); + + printf(">>%02d RI %d SEC %s CH %02d BSSID %02X:%02X:%02X:%02X:%02X:%02X SSID %s\n", + pstrScanResult->u8index,pstrScanResult->s8rssi, + pstrScanResult->u8AuthType, + pstrScanResult->u8ch, + pstrScanResult->au8BSSID[0], pstrScanResult->au8BSSID[1], pstrScanResult->au8BSSID[2], + pstrScanResult->au8BSSID[3], pstrScanResult->au8BSSID[4], pstrScanResult->au8BSSID[5], + pstrScanResult->au8SSID); + + if(u8ScanResultIdx < u8NumFoundAPs) + { + // Read the next scan result + m2m_wifi_req_scan_result(index); + u8ScanResultIdx ++; + } + } + break; + default: + break; + } + } + + static void request_scan_hidden_demo_ap(void) + { + uint8 list[9]; + char ssid[] = "DEMO_AP"; + uint8 len = (uint8)(sizeof(ssid)-1); + + list[0] = 1; + list[1] = len; + memcpy(&list[2], ssid, len); // copy 7 bytes + // Scan all channels + m2m_wifi_request_scan_ssid_list(M2M_WIFI_CH_ALL, list); + } + + + int main() + { + tstrWifiInitParam param; + + param.pfAppWifiCb = wifi_event_cb; + if(!m2m_wifi_init(¶m)) + { + request_scan_hidden_demo_ap(); + + while(1) + { + m2m_wifi_handle_events(NULL); + } + } + } + +@endcode +*/ +NMI_API sint8 m2m_wifi_request_scan_ssid_list(uint8 ch,uint8 * u8Ssidlist); + +/**@}*/ +/** @defgroup WifiGetNumAPFoundFn m2m_wifi_get_num_ap_found + * @ingroup WLANAPI +* Synchronous function to retrieve the number of AP's found in the last scan request, The function reads the number of APs from global variable which was updated in the Wi-Fi callback function through the M2M_WIFI_RESP_SCAN_DONE event. +* Function used only in STA mode only. + */ + /**@{*/ +/*! +@fn NMI_API uint8 m2m_wifi_get_num_ap_found(void); + +@see m2m_wifi_request_scan + M2M_WIFI_RESP_SCAN_DONE + M2M_WIFI_RESP_SCAN_RESULT +@pre m2m_wifi_request_scan need to be called first + - A Wi-Fi notification callback of type @ref tpfAppWifiCb MUST be implemented and registered at initialization. Registering the callback + is done through passing it to the @ref m2m_wifi_init. + - The event @ref M2M_WIFI_RESP_SCAN_DONE must be handled in the callback to receive the requested scan information. +@warning This function must be called only in the wi-fi callback function when the events @ref M2M_WIFI_RESP_SCAN_DONE or @ref M2M_WIFI_RESP_SCAN_RESULT + are received. + Calling this function in any other place will result in undefined/outdated numbers. +@return Return the number of AP's found in the last Scan Request. + +\section Example + The code snippet demonstrates an example of how the scan request is called from the application's main function and the handling of + the events received in response. +@code + + #include "m2m_wifi.h" + #include "m2m_types.h" + + void wifi_event_cb(uint8 u8WiFiEvent, void * pvMsg) + { + static uint8 u8ScanResultIdx = 0; + + switch(u8WiFiEvent) + { + case M2M_WIFI_RESP_SCAN_DONE: + { + tstrM2mScanDone *pstrInfo = (tstrM2mScanDone*)pvMsg; + + printf("Num of AP found %d\n",pstrInfo->u8NumofCh); + if(pstrInfo->s8ScanState == M2M_SUCCESS) + { + u8ScanResultIdx = 0; + if(pstrInfo->u8NumofCh >= 1) + { + m2m_wifi_req_scan_result(u8ScanResultIdx); + u8ScanResultIdx ++; + } + else + { + printf("No AP Found Rescan\n"); + m2m_wifi_request_scan(M2M_WIFI_CH_ALL); + } + } + else + { + printf("(ERR) Scan fail with error <%d>\n",pstrInfo->s8ScanState); + } + } + break; + + case M2M_WIFI_RESP_SCAN_RESULT: + { + tstrM2mWifiscanResult *pstrScanResult =(tstrM2mWifiscanResult*)pvMsg; + uint8 u8NumFoundAPs = m2m_wifi_get_num_ap_found(); + + printf(">>%02d RI %d SEC %s CH %02d BSSID %02X:%02X:%02X:%02X:%02X:%02X SSID %s\n", + pstrScanResult->u8index,pstrScanResult->s8rssi, + pstrScanResult->u8AuthType, + pstrScanResult->u8ch, + pstrScanResult->au8BSSID[0], pstrScanResult->au8BSSID[1], pstrScanResult->au8BSSID[2], + pstrScanResult->au8BSSID[3], pstrScanResult->au8BSSID[4], pstrScanResult->au8BSSID[5], + pstrScanResult->au8SSID); + + if(u8ScanResultIdx < u8NumFoundAPs) + { + // Read the next scan result + m2m_wifi_req_scan_result(index); + u8ScanResultIdx ++; + } + } + break; + default: + break; + } + } + + int main() + { + tstrWifiInitParam param; + + param.pfAppWifiCb = wifi_event_cb; + if(!m2m_wifi_init(¶m)) + { + // Scan all channels + m2m_wifi_request_scan(M2M_WIFI_CH_ALL); + + while(1) + { + m2m_wifi_handle_events(NULL); + } + } + } + +@endcode +*/ +NMI_API uint8 m2m_wifi_get_num_ap_found(void); +/**@}*/ +/** @defgroup WifiReqScanResult m2m_wifi_req_scan_result +* @ingroup WLANAPI +* Synchronous call to read the AP information from the SCAN Result list with the given index. +* This function is expected to be called when the response events M2M_WIFI_RESP_SCAN_RESULT or +* M2M_WIFI_RESP_SCAN_DONE are received in the wi-fi callback function. +* The response information received can be obtained through the casting to the @ref tstrM2mWifiscanResult structure + */ + /**@{*/ +/*! +@fn NMI_API sint8 m2m_wifi_req_scan_result(uint8 index); +@param [in] index + Index for the requested result, the index range start from 0 till number of AP's found + +@see tstrM2mWifiscanResult + m2m_wifi_get_num_ap_found + m2m_wifi_request_scan + +@pre @ref m2m_wifi_request_scan needs to be called first, then m2m_wifi_get_num_ap_found + to get the number of AP's found + - A Wi-Fi notification callback of type @ref tpfAppWifiCb MUST be implemented and registered at startup. Registering the callback + is done through passing it to the @ref m2m_wifi_init function. + - The event @ref M2M_WIFI_RESP_SCAN_RESULT must be handled in the callback to receive the requested scan information. +@warning Function used in STA mode only. the scan results are updated only if the scan request is called. + Calling this function only without a scan request will lead to firmware errors. + Refrain from introducing a large delay between the scan request and the scan result request, to prevent + errors occurring. + +@return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +\section Example + The code snippet demonstrates an example of how the scan request is called from the application's main function and the handling of + the events received in response. +@code + #include "m2m_wifi.h" + #include "m2m_types.h" + + void wifi_event_cb(uint8 u8WiFiEvent, void * pvMsg) + { + static uint8 u8ScanResultIdx = 0; + + switch(u8WiFiEvent) + { + case M2M_WIFI_RESP_SCAN_DONE: + { + tstrM2mScanDone *pstrInfo = (tstrM2mScanDone*)pvMsg; + + printf("Num of AP found %d\n",pstrInfo->u8NumofCh); + if(pstrInfo->s8ScanState == M2M_SUCCESS) + { + u8ScanResultIdx = 0; + if(pstrInfo->u8NumofCh >= 1) + { + m2m_wifi_req_scan_result(u8ScanResultIdx); + u8ScanResultIdx ++; + } + else + { + printf("No AP Found Rescan\n"); + m2m_wifi_request_scan(M2M_WIFI_CH_ALL); + } + } + else + { + printf("(ERR) Scan fail with error <%d>\n",pstrInfo->s8ScanState); + } + } + break; + + case M2M_WIFI_RESP_SCAN_RESULT: + { + tstrM2mWifiscanResult *pstrScanResult =(tstrM2mWifiscanResult*)pvMsg; + uint8 u8NumFoundAPs = m2m_wifi_get_num_ap_found(); + + printf(">>%02d RI %d SEC %s CH %02d BSSID %02X:%02X:%02X:%02X:%02X:%02X SSID %s\n", + pstrScanResult->u8index,pstrScanResult->s8rssi, + pstrScanResult->u8AuthType, + pstrScanResult->u8ch, + pstrScanResult->au8BSSID[0], pstrScanResult->au8BSSID[1], pstrScanResult->au8BSSID[2], + pstrScanResult->au8BSSID[3], pstrScanResult->au8BSSID[4], pstrScanResult->au8BSSID[5], + pstrScanResult->au8SSID); + + if(u8ScanResultIdx < u8NumFoundAPs) + { + // Read the next scan result + m2m_wifi_req_scan_result(index); + u8ScanResultIdx ++; + } + } + break; + default: + break; + } + } + + int main() + { + tstrWifiInitParam param; + + param.pfAppWifiCb = wifi_event_cb; + if(!m2m_wifi_init(¶m)) + { + // Scan all channels + m2m_wifi_request_scan(M2M_WIFI_CH_ALL); + + while(1) + { + m2m_wifi_handle_events(NULL); + } + } + } + +@endcode +*/ +NMI_API sint8 m2m_wifi_req_scan_result(uint8 index); +/**@}*/ +/** @defgroup WifiReqCurrentRssiFn m2m_wifi_req_curr_rssi + * @ingroup WLANAPI + * Asynchronous request for the current RSSI of the connected AP. + * The response received in through the @ref M2M_WIFI_RESP_CURRENT_RSSI event. + */ + /**@{*/ +/*! +@fn NMI_API sint8 m2m_wifi_req_curr_rssi(void); +@pre - A Wi-Fi notification callback of type @ref tpfAppWifiCb MUST be implemented and registered before initialization. Registering the callback + is done through passing it to the [m2m_wifi_init](@ref m2m_wifi_init) through the @ref tstrWifiInitParam initialization structure. + - The event @ref M2M_WIFI_RESP_CURRENT_RSSI must be handled in the callback to receive the requested Rssi information. +@return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +\section Example + The code snippet demonstrates how the RSSI request is called in the application's main function and the handling of the event received in the callback. +@code + + #include "m2m_wifi.h" + #include "m2m_types.h" + + void wifi_event_cb(uint8 u8WiFiEvent, void * pvMsg) + { + static uint8 u8ScanResultIdx = 0; + + switch(u8WiFiEvent) + { + case M2M_WIFI_RESP_CURRENT_RSSI: + { + sint8 *rssi = (sint8*)pvMsg; + M2M_INFO("ch rssi %d\n",*rssi); + } + break; + default: + break; + } + } + + int main() + { + tstrWifiInitParam param; + + param.pfAppWifiCb = wifi_event_cb; + if(!m2m_wifi_init(¶m)) + { + // Scan all channels + m2m_wifi_req_curr_rssi(); + + while(1) + { + m2m_wifi_handle_events(NULL); + } + } + } + +@endcode + +*/ +NMI_API sint8 m2m_wifi_req_curr_rssi(void); +/**@}*/ +/** @defgroup WifiGetOtpMacAddFn m2m_wifi_get_otp_mac_address +* @ingroup WLANAPI +* Request the MAC address stored on the One Time Programmable(OTP) memory of the device. +* The function is blocking until the response is received. +*/ + /**@{*/ +/*! +@fn NMI_API sint8 m2m_wifi_get_otp_mac_address(uint8 *pu8MacAddr, uint8 * pu8IsValid); + +@param [out] pu8MacAddr + Output MAC address buffer of 6 bytes size. Valid only if *pu8Valid=1. +@param [out] pu8IsValid + Output boolean value to indicate the validity of pu8MacAddr in OTP. + Output zero if the OTP memory is not programmed, non-zero otherwise. +@pre m2m_wifi_init required to be called before any WIFI/socket function +@see m2m_wifi_get_mac_address + +@return The function returns @ref M2M_SUCCESS for success and a negative value otherwise. + +*/ +NMI_API sint8 m2m_wifi_get_otp_mac_address(uint8 *pu8MacAddr, uint8 * pu8IsValid); +/**@}*/ +/** @defgroup WifiGetMacAddFn m2m_wifi_get_mac_address +* @ingroup WLANAPI +* Function to retrieve the current MAC address. The function is blocking until the response is received. +*/ +/**@{*/ +/*! +@fn NMI_API sint8 m2m_wifi_get_mac_address(uint8 *pu8MacAddr) +@param [out] pu8MacAddr + Output MAC address buffer of 6 bytes size. +@pre m2m_wifi_init required to be called before any WIFI/socket function +@see m2m_wifi_get_otp_mac_address +@return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. + +*/ +NMI_API sint8 m2m_wifi_get_mac_address(uint8 *pu8MacAddr); +/**@}*/ +/** @defgroup SetSleepModeFn m2m_wifi_set_sleep_mode + * @ingroup WLANAPI + * This is one of the two synchronous power-save setting functions that + * allow the host MCU application to tweak the system power consumption. Such tweaking can be done through one of two ways: +* 1) Changing the power save mode, to one of the allowed power save modes @ref tenuPowerSaveModes. This is done by setting the first parameter +* 2) Configuring DTIM monitoring: Configuring beacon monitoring parameters by enabling or disabling the reception of broadcast/multicast data. +* this is done by setting the second parameter. + */ + /**@{*/ +/*! +@fn NMI_API sint8 m2m_wifi_set_sleep_mode(uint8 PsTyp, uint8 BcastEn); +@param [in] PsTyp + Desired power saving mode. Supported types are enumerated in @ref tenuPowerSaveModes. +@param [in] BcastEn + Broadcast reception enable flag. + If it is 1, the WINC1500 will be awake each DTIM beacon for receiving broadcast traffic. + If it is 0, the WINC1500: disable broadcast traffic. Through this flag the WINC1500 will not wakeup at the DTIM beacon, but it will wakeup depends only + on the the configured Listen Interval. + +@warning The function called once after initialization. + +@see tenuPowerSaveModes + m2m_wifi_get_sleep_mode + m2m_wifi_set_lsn_int + +@return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +*/ +NMI_API sint8 m2m_wifi_set_sleep_mode(uint8 PsTyp, uint8 BcastEn); +/**@}*/ +/** @defgroup WifiRequestSleepFn m2m_wifi_request_sleep + * @ingroup WLANAPI + * Synchronous power-save sleep request function, which requests from the WINC1500 device to sleep in the currenlty configured power save mode as defined + * by the @ref m2m_wifi_set_sleep_mode, for a specific time as defined by the passed in parameter. + * This function should be used in the @ref M2M_PS_MANUAL power save mode only. + * A wake up request is automatically performed by the WINC1500 device when any host driver API function, e.g. Wi-Fi or socket operation is called. + */ + /**@{*/ +/*! +@fn NMI_API sint8 m2m_wifi_request_sleep(uint32 u32SlpReqTime); +@param [in] u32SlpReqTime + Request sleep time in ms + The best recommended sleep duration is left to be determined by the application. Taking into account that if the application sends notifications very rarely, + sleeping for a long time can be a power-efficient decision. In contrast applications that are senstive for long periods of absence can experience + performance degradation in the connection if long sleeping times are used. +@warning The function should be called in @ref M2M_PS_MANUAL power save mode only. As enumerated in @ref tenuPowerSaveModes + It's also important to note that during the sleeping time while in the M2M_PS_MANUAL mode, AP beacon monitoring is bypassed and the wifi-connection may drop if + the sleep period is enlongated. +@see tenuPowerSaveModes + m2m_wifi_set_sleep_mode + +@return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +*/ +NMI_API sint8 m2m_wifi_request_sleep(uint32 u32SlpReqTime); +/**@}*/ +/** @defgroup GetSleepModeFn m2m_wifi_get_sleep_mode + * @ingroup WLANAPI + * Synchronous power save mode retrieval function. + */ + /**@{*/ +/*! +@fn NMI_API uint8 m2m_wifi_get_sleep_mode(void); +@see tenuPowerSaveModes + m2m_wifi_set_sleep_mode +@return The current operating power saving mode based on the enumerated sleep modes @ref tenuPowerSaveModes. +*/ +NMI_API uint8 m2m_wifi_get_sleep_mode(void); +/**@}*/ +/** @defgroup WifiReqClientCtrlFn m2m_wifi_req_client_ctrl + * @ingroup WLANAPI + * Asynchronous command sending function to the PS Client (An WINC1500 board running the ps_firmware) +* if the PS client send any command it will be received through the @ref M2M_WIFI_RESP_CLIENT_INFO event + */ + /**@{*/ +/*! +@fn NMI_API sint8 m2m_wifi_req_client_ctrl(uint8 cmd); +@brief +@param [in] cmd + Control command sent from PS Server to PS Client (command values defined by the application) +@pre @ref m2m_wifi_req_server_init should be called first +@warning This mode is not supported in the current release. +@see m2m_wifi_req_server_init + M2M_WIFI_RESP_CLIENT_INFO +@return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +*/ +NMI_API sint8 m2m_wifi_req_client_ctrl(uint8 cmd); +/**@}*/ +/** @defgroup WifiReqServerInit m2m_wifi_req_server_init + * @ingroup WLANAPI + * Synchronous function to initialize the PS Server. + * The WINC1500 supports non secure communication with another WINC1500, +* (SERVER/CLIENT) through one byte command (probe request and probe response) without any connection setup. +* The server mode can't be used with any other modes (STA/P2P/AP) +*/ + /**@{*/ +/*! +@fn NMI_API sint8 m2m_wifi_req_server_init(uint8 ch); +@param [in] ch + Server listening channel +@see m2m_wifi_req_client_ctrl +@warning This mode is not supported in the current release. +@return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +*/ +NMI_API sint8 m2m_wifi_req_server_init(uint8 ch); +/**@}*/ +/** @defgroup WifiSetDeviceNameFn m2m_wifi_set_device_name + * @ingroup WLANAPI + * Sets the WINC device name. The name string is used as a device name in both (P2P) WiFi-Direct mode as well as DHCP hostname (option 12). + * For P2P devices to communicate a device name must be present. If it is not set through this function a default name is assigned. + * The default name is WINC-XX-YY, where XX and YY are the last 2 octets of the OTP MAC address. If OTP (eFuse) is programmed, + * then the default name is WINC-00-00. + */ + /**@{*/ +/*! +@fn NMI_API sint8 m2m_wifi_set_device_name(uint8 *pu8DeviceName, uint8 u8DeviceNameLength); +@param [in] pu8DeviceName + A Buffer holding the device name. Device name is a null terminated C string. +@param [in] u8DeviceNameLength + The length of the device name. Should not exceed the maximum device name's length @ref M2M_DEVICE_NAME_MAX (including null character). +@warning The function called once after initialization. + Used for the Wi-Fi Direct (P2P) as well as DHCP client hostname option (12). +@warning Device name shall contain only characters allowed in valid internet host name as defined in RFC 952 and 1123. +@return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +*/ +NMI_API sint8 m2m_wifi_set_device_name(uint8 *pu8DeviceName, uint8 u8DeviceNameLength); +/**@}*/ +/** @defgroup WifiSetLsnIntFn m2m_wifi_set_lsn_int + * @ingroup WLANAPI +* This is one of the two synchronous power-save setting functions that +* allow the host MCU application to tweak the system power consumption. Such tweaking can be done by modifying the +* the Wi-Fi listen interval. The listen interval is how many beacon periods the station can sleep before it wakes up to receive data buffer in AP. +* It is represented in units of AP beacon periods(100ms). +*/ + /**@{*/ +/*! +@fn NMI_API sint8 m2m_wifi_set_lsn_int(tstrM2mLsnInt * pstrM2mLsnInt); + +@param [in] pstrM2mLsnInt + Structure holding the listen interval configurations. +@pre Function @m2m_wifi_set_sleep_mode shall be called first, to set the power saving mode required. +@warning The function should be called once after initialization. +@see tstrM2mLsnInt + m2m_wifi_set_sleep_mode +@return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. + +*/ +NMI_API sint8 m2m_wifi_set_lsn_int(tstrM2mLsnInt *pstrM2mLsnInt); +/**@}*/ +/** @defgroup WifiEnableMonitorModeFn m2m_wifi_enable_monitoring_mode + * @ingroup WLANAPI + * Asynchronous Wi-Fi monitoring mode (Promiscuous mode) enabling function. This function enables the monitoring mode, thus allowing two operations to be performed: + * 1) Transmission of manually configured frames, through using the @ref m2m_wifi_send_wlan_pkt function. + * 2) Reception of frames based on a defined filtering criteria + * When the monitoring mode is enabled, reception of all frames that satisfy the filter criteria passed in as a parameter is allowed, on the current wireless channel \n. + * All packets that meet the filtering criteria are passed to the application layer, to be handled by the assigned monitoring callback function \n. + * The monitoring callback function must be implemented before starting the monitoring mode, in-order to handle the packets received \n. + * Registering of the implemented callback function is through the callback pointer @ref tpfAppMonCb in the @ref tstrWifiInitParam structure\n. + * passed to @ref m2m_wifi_init function at initialization. + * + */ + /**@{*/ +/*! + * @fn NMI_API sint8 m2m_wifi_enable_monitoring_mode(tstrM2MWifiMonitorModeCtrl *, uint8 *, uint16 , uint16); + * @param [in] pstrMtrCtrl + * Pointer to @ref tstrM2MWifiMonitorModeCtrl structure holding the filtering parameters. + * @param [in] pu8PayloadBuffer + * Pointer to a buffer allocated by the application. The buffer SHALL hold the Data field of + * the WIFI RX Packet (Or a part from it). If it is set to NULL, the WIFI data payload will + * be discarded by the monitoring driver. + * @param [in] u16BufferSize + * The total size of the pu8PayloadBuffer in bytes. + * @param [in] u16DataOffset + * Starting offset in the DATA FIELD of the received WIFI packet. The application may be interested + * in reading specific information from the received packet. It must assign the offset to the starting + * position of it relative to the DATA payload start.\n + * \e Example, \e if \e the \e SSID \e is \e needed \e to \e be \e read \e from \e a \e PROBE \e REQ \e packet, \e the \e u16Offset \e MUST \e be \e set \e to \e 0. + * @warning When This mode is enabled, you can not be connected in any mode (Station, Access Point, or P2P).\n + * @see tstrM2MWifiMonitorModeCtrl + tstrM2MWifiRxPacketInfo + tstrWifiInitParam + tenuM2mScanCh + m2m_wifi_disable_monitoring_mode + m2m_wifi_send_wlan_pkt + m2m_wifi_send_ethernet_pkt + * @return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. + +*\section Example +* The example demonstrates the main function where-by the monitoring enable function is called after the initialization of the driver and the packets are +* handled in the callback function. +* @code + + #include "m2m_wifi.h" + #include "m2m_types.h" + + //Declare receive buffer + uint8 gmgmt[1600]; + + //Callback functions + void wifi_cb(uint8 u8WiFiEvent, void * pvMsg) + { + ; + } + void wifi_monitoring_cb(tstrM2MWifiRxPacketInfo *pstrWifiRxPacket, uint8 *pu8Payload, uint16 u16PayloadSize) + { + if((NULL != pstrWifiRxPacket) && (0 != u16PayloadSize)) { + if(MANAGEMENT == pstrWifiRxPacket->u8FrameType) { + M2M_INFO("***# MGMT PACKET #***\n"); + } else if(DATA_BASICTYPE == pstrWifiRxPacket->u8FrameType) { + M2M_INFO("***# DATA PACKET #***\n"); + } else if(CONTROL == pstrWifiRxPacket->u8FrameType) { + M2M_INFO("***# CONTROL PACKET #***\n"); + } + } + } + + int main() + { + //Register wifi_monitoring_cb + tstrWifiInitParam param; + param.pfAppWifiCb = wifi_cb; + param.pfAppMonCb = wifi_monitoring_cb; + + nm_bsp_init(); + + if(!m2m_wifi_init(¶m)) { + //Enable Monitor Mode with filter to receive all data frames on channel 1 + tstrM2MWifiMonitorModeCtrl strMonitorCtrl = {0}; + strMonitorCtrl.u8ChannelID = M2M_WIFI_CH_1; + strMonitorCtrl.u8FrameType = DATA_BASICTYPE; + strMonitorCtrl.u8FrameSubtype = M2M_WIFI_FRAME_SUB_TYPE_ANY; //Receive any subtype of data frame + m2m_wifi_enable_monitoring_mode(&strMonitorCtrl, gmgmt, sizeof(gmgmt), 0); + + while(1) { + m2m_wifi_handle_events(NULL); + } + } + return 0; + } + * @endcode + */ +NMI_API sint8 m2m_wifi_enable_monitoring_mode(tstrM2MWifiMonitorModeCtrl *pstrMtrCtrl, uint8 *pu8PayloadBuffer, + uint16 u16BufferSize, uint16 u16DataOffset); +/**@}*/ +/** @defgroup WifiDisableMonitorModeFn m2m_wifi_disable_monitoring_mode + * @ingroup WLANAPI + * Synchronous function to disable Wi-Fi monitoring mode (Promiscuous mode). Expected to be called, if the enable monitoring mode is set, but if it was called without enabling + * no negative impact will reside. + */ + /**@{*/ +/*! + * @fn NMI_API sint8 m2m_wifi_disable_monitoring_mode(void); + * @see m2m_wifi_enable_monitoring_mode + * @return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. + */ +NMI_API sint8 m2m_wifi_disable_monitoring_mode(void); + /**@}*/ + /** @defgroup SendWlanPktFn m2m_wifi_send_wlan_pkt + * @ingroup WLANAPI + * Synchronous function to transmit a WIFI RAW packet while the implementation of this packet is left to the application developer. + */ + /**@{*/ +/*! + * @fn NMI_API sint8 m2m_wifi_send_wlan_pkt(uint8 *, uint16, uint16); + + * @param [in] pu8WlanPacket + * Pointer to a buffer holding the whole WIFI frame. + * @param [in] u16WlanHeaderLength + * The size of the WIFI packet header ONLY. + * @param [in] u16WlanPktSize + * The size of the whole bytes in packet. + * @see m2m_wifi_enable_monitoring_mode + m2m_wifi_disable_monitoring_mode + * @pre Enable Monitoring mode first using @ref m2m_wifi_enable_monitoring_mode + * @warning This function available in monitoring mode ONLY.\n + * @note Packets are user's responsibility. + * @return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. + */ +NMI_API sint8 m2m_wifi_send_wlan_pkt(uint8 *pu8WlanPacket, uint16 u16WlanHeaderLength, uint16 u16WlanPktSize); +/**@}*/ +/** @defgroup WifiSendEthernetPktFn m2m_wifi_send_ethernet_pkt + * @ingroup WLANAPI + * Synchronous function to transmit an Ethernet packet. Transmit a packet directly in ETHERNET/bypass mode where the TCP/IP stack is disabled and the implementation of this packet is left to the application developer. + * The Ethernet packet composition is left to the application developer. + */ + /**@{*/ +/*! + * @fn NMI_API sint8 m2m_wifi_send_ethernet_pkt(uint8* pu8Packet,uint16 u16PacketSize) + * @param [in] pu8Packet + * Pointer to a buffer holding the whole Ethernet frame. + * @param [in] u16PacketSize + * The size of the whole bytes in packet. + * @warning This function available in ETHERNET/Bypass mode ONLY. Make sure that application defines @ref ETH_MODE.\n + * @note Packets are the user's responsibility. + * @sa m2m_wifi_enable_mac_mcast,m2m_wifi_set_receive_buffer + * @return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. + + */ +NMI_API sint8 m2m_wifi_send_ethernet_pkt(uint8* pu8Packet,uint16 u16PacketSize); +/**@}*/ +/** @defgroup WifiEnableSntpFn m2m_wifi_enable_sntp + * @ingroup WLANAPI + * Synchronous function to enable/disable the native Simple Network Time Protocol(SNTP) client in the WINC1500 firmware.\n + * The SNTP is enabled by default at start-up.The SNTP client at firmware is used to synchronize the system clock to the UTC time from the well known time + * servers (e.g. "time-c.nist.gov"). The SNTP client uses a default update cycle of 1 day. + * The UTC is important for checking the expiration date of X509 certificates used while establishing + * TLS (Transport Layer Security) connections. + * It is highly recommended to use it if there is no other means to get the UTC time. If there is a RTC + * on the host MCU, the SNTP could be disabled and the host should set the system time to the firmware + * using the @ref m2m_wifi_set_system_time function. + */ + /**@{*/ +/*! + * @fn NMI_API sint8 m2m_wifi_enable_sntp(uint8); + * @param [in] bEnable +* Enabling/Disabling flag + * '0' :disable SNTP + * '1' :enable SNTP + * @see m2m_wifi_set_sytem_time + * @return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. + */ +NMI_API sint8 m2m_wifi_enable_sntp(uint8 bEnable); +/**@}*/ +/** @defgroup WifiSetSystemTime m2m_wifi_set_sytem_time + * @ingroup WLANAPI + * Synchronous function for setting the system time in time/date format (@ref uint32).\n + * The @ref tstrSystemTime structure can be used as a reference to the time values that should be set and pass its value as @ref uint32 + */ + /**@{*/ +/*! + * @fn NMI_API sint8 m2m_wifi_set_sytem_time(uint32); + * @param [in] u32UTCSeconds + * Seconds elapsed since January 1, 1900 (NTP Timestamp). + * @see m2m_wifi_enable_sntp + * tstrSystemTime + * @note If there is an RTC on the host MCU, the SNTP could be disabled and the host should set the system time to the firmware + * using the API @ref m2m_wifi_set_sytem_time. + * @return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. + */ +NMI_API sint8 m2m_wifi_set_sytem_time(uint32 u32UTCSeconds); +/**@}*/ +/** @defgroup WifiGetSystemTime m2m_wifi_get_sytem_time + * @ingroup WLANAPI + * Asynchronous function used to retrieve the system time through the use of the response @ref M2M_WIFI_RESP_GET_SYS_TIME. + * Response time retrieved is parsed into the members defined in the structure @ref tstrSystemTime. + */ + /**@{*/ +/*! + * @fn NMI_API sint8 m2m_wifi_get_sytem_time(void); + * @see m2m_wifi_enable_sntp + tstrSystemTime + * @note Get the system time from the SNTP client + * using the API @ref m2m_wifi_get_sytem_time. + * @return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. + */ +NMI_API sint8 m2m_wifi_get_sytem_time(void); +/**@}*/ +/** @defgroup WifiSetCustInfoElementFn m2m_wifi_set_cust_InfoElement + * @ingroup WLANAPI + * Synchronous function to Add/Remove user-defined Information Element to the WIFIBeacon and Probe Response frames while chip mode is Access Point Mode.\n + * According to the information element layout shown bellow, if it is required to set new data for the information elements, pass in the buffer with the + * information according to the sizes and ordering defined bellow. However, if it's required to delete these IEs, fill the buffer with zeros. + */ + /**@{*/ +/*! + * @fn NMI_API sint8 m2m_wifi_set_cust_InfoElement(uint8*); + * @param [in] pau8M2mCustInfoElement + * Pointer to Buffer containing the IE to be sent. It is the application developer's responsibility to ensure on the correctness of the information element's ordering passed in. + * @warning - Size of All elements combined must not exceed 255 byte.\n + * - Used in Access Point Mode \n + * @note IEs Format will be follow the following layout:\n + * @verbatim + --------------- ---------- ---------- ------------------- -------- -------- ----------- ---------------------- + | Byte[0] | Byte[1] | Byte[2] | Byte[3:length1+2] | ..... | Byte[n] | Byte[n+1] | Byte[n+2:lengthx+2] | + |---------------|----------|----------|-------------------|-------- --------|-----------|------------------| + | #of all Bytes | IE1 ID | Length1 | Data1(Hex Coded) | ..... | IEx ID | Lengthx | Datax(Hex Coded) | + --------------- ---------- ---------- ------------------- -------- -------- ----------- ---------------------- + * @endverbatim + * @see m2m_wifi_enable_sntp + * tstrSystemTime + * @return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. + \section Example + The example demonstrates how the information elements are set using this function. + *@code + * + char elementData[21]; + static char state = 0; // To Add, Append, and Delete + if(0 == state) { //Add 3 IEs + state = 1; + //Total Number of Bytes + elementData[0]=12; + //First IE + elementData[1]=200; elementData[2]=1; elementData[3]='A'; + //Second IE + elementData[4]=201; elementData[5]=2; elementData[6]='B'; elementData[7]='C'; + //Third IE + elementData[8]=202; elementData[9]=3; elementData[10]='D'; elementData[11]=0; elementData[12]='F'; + } else if(1 == state) { + //Append 2 IEs to others, Notice that we keep old data in array starting with\n + //element 13 and total number of bytes increased to 20 + state = 2; + //Total Number of Bytes + elementData[0]=20; + //Fourth IE + elementData[13]=203; elementData[14]=1; elementData[15]='G'; + //Fifth IE + elementData[16]=204; elementData[17]=3; elementData[18]='X'; elementData[19]=5; elementData[20]='Z'; + } else if(2 == state) { //Delete All IEs + state = 0; + //Total Number of Bytes + elementData[0]=0; + } + m2m_wifi_set_cust_InfoElement(elementData); + * @endcode + */ +NMI_API sint8 m2m_wifi_set_cust_InfoElement(uint8* pau8M2mCustInfoElement); + /**@}*/ +/** @defgroup WifiSetPowerProfile m2m_wifi_set_power_profile + * @ingroup WLANAPI + * Change the power profile mode + */ + /**@{*/ +/*! +@fn NMI_API sint8 m2m_wifi_set_power_profile(uint8 u8PwrMode); +@brief +@param [in] u8PwrMode + Change the WINC1500 power profile to different mode based on the enumeration + @ref tenuM2mPwrMode +@pre Must be called after the initializations and before any connection request and can't be changed in run time. +@sa tenuM2mPwrMode + m2m_wifi_init +@return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +*/ +sint8 m2m_wifi_set_power_profile(uint8 u8PwrMode); + /**@}*/ + /** @defgroup WifiSetTxPower m2m_wifi_set_tx_power + * @ingroup WLANAPI + * Set the TX power tenuM2mTxPwrLevel + */ + /**@{*/ +/*! +@fn NMI_API sint8 m2m_wifi_set_tx_power(uint8 u8TxPwrLevel); +@param [in] u8TxPwrLevel + change the TX power based on the enumeration tenuM2mTxPwrLevel +@pre Must be called after the initialization and before any connection request and can't be changed in runtime. +@sa tenuM2mTxPwrLevel + m2m_wifi_init +@return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +*/ +sint8 m2m_wifi_set_tx_power(uint8 u8TxPwrLevel); + /**@}*/ +/** @defgroup WifiEnableFirmware m2m_wifi_enable_firmware_logs +* @ingroup WLANAPI +* Enable or Disable logs in run time (Disabling Firmware logs will +* enhance the firmware start-up time and performance) +*/ + /**@{*/ +/*! +@fn NMI_API sint8 m2m_wifi_enable_firmware_logs(uint8 u8Enable); +@param [in] u8Enable + Set 1 to enable the logs, 0 for disable +@pre Must be called after intialization through the following function @ref m2m_wifi_init +@sa __DISABLE_FIRMWARE_LOGS__ (build option to disable logs from initializations) + m2m_wifi_init +@return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +*/ +sint8 m2m_wifi_enable_firmware_logs(uint8 u8Enable); + /**@}*/ + /** @defgroup WifiSetBatteryVoltage m2m_wifi_set_battery_voltage +* @ingroup WLANAPI +* Set the battery voltage to update the firmware calculations +*/ + /**@{*/ +/*! +@fn NMI_API sint8 m2m_wifi_set_battery_voltage(uint8 u8BattVolt) +@brief Set the battery voltage to update the firmware calculations +@param [in] dbBattVolt + Battery Volt in double +@pre Must be called after intialization through the following function @ref m2m_wifi_init +@sa m2m_wifi_init +@return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +*/ +sint8 m2m_wifi_set_battery_voltage(uint16 u16BattVoltx100); + /**@}*/ + /** @defgroup WifiSetGains m2m_wifi_set_gains +* @ingroup WLANAPI +* Set the chip gains mainly (PPA for 11b/11gn) +*/ + /**@{*/ +/*! +@fn sint8 m2m_wifi_set_gains(tstrM2mWifiGainsParams* pstrM2mGain); +@brief Set the chip PPA gain for 11b/11gn +@param [in] pstrM2mGain + tstrM2mWifiGainsParams contain gain parmaters as implemnted in rf document +@pre Must be called after intialization through the following function @ref m2m_wifi_init +@sa m2m_wifi_init +@return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +*/ +sint8 m2m_wifi_set_gains(tstrM2mWifiGainsParams* pstrM2mGain); + /**@}*/ +/** @defgroup WifiGetFirmwareVersion m2m_wifi_get_firmware_version +* @ingroup WLANAPI +* Get Firmware version info as defined in the structure @ref tstrM2mRev. +*/ + /**@{*/ +/*! +@fn m2m_wifi_get_firmware_version(tstrM2mRev* pstrRev) +@param [out] M2mRev + Pointer to the structure @ref tstrM2mRev that contains the firmware version parameters +@pre Must be called after intialization through the following function @ref m2m_wifi_init +@sa m2m_wifi_init +@return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +*/ +sint8 m2m_wifi_get_firmware_version(tstrM2mRev *pstrRev); +/**@}*/ +#ifdef ETH_MODE +/** @defgroup WifiEnableMacMcastFn m2m_wifi_enable_mac_mcast + * @ingroup WLANAPI + * Synchronous function for filtering received MAC addresses from certain MAC address groups. + * This function allows the addtion/removal of certain MAC addresses, used in the multicast filter. + */ + /**@{*/ +/*! + * @fn NMI_API sint8 m2m_wifi_enable_mac_mcast(uint8 *, uint8); + * @brief + * @param [in] pu8MulticastMacAddress + * Pointer to MAC address + * @param [in] u8AddRemove + * A flag to add or remove the MAC ADDRESS, based on the following values: + * - 0 : remove MAC address + * - 1 : add MAC address + * @warning This function is available in ETHERNET/bypass mode ONLY. Make sure that the application defines @ref ETH_MODE.\n + * @note Maximum number of MAC addresses that could be added is 8. + * @sa m2m_wifi_set_receive_buffer, m2m_wifi_send_ethernet_pkt + * @return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. + */ +NMI_API sint8 m2m_wifi_enable_mac_mcast(uint8* pu8MulticastMacAddress, uint8 u8AddRemove); +/**@}*/ +/** @defgroup SetReceiveBufferFn m2m_wifi_set_receive_buffer + * @ingroup WLANAPI + * Synchronous function for setting or modifying the receiver buffer's length. + * In the ETHERNET/bypass mode the application should define a callback of type @ref tpfAppEthCb, through which the application handles the received + * ethernet frames. It is through this callback function that the user can dynamically modify the length of the currently used receiver buffer. + *@{*/ +/*! + * @fn NMI_API sint8 m2m_wifi_set_receive_buffer(void *, uint16); + + * @param [in] pvBuffer + * Pointer to Buffer to receive data. + * NULL pointer causes a negative error @ref M2M_ERR_FAIL. + * + * @param [in] u16BufferLen + * Length of data to be received. Maximum length of data should not exceed the size defined by TCP/IP + * defined as @ref SOCKET_BUFFER_MAX_LENGTH + * + * @warning This function is available in the Ethernet/bypass mode ONLY. Make sure that the application defines @ref ETH_MODE.\n + * @sa m2m_wifi_enable_mac_mcast,m2m_wifi_send_ethernet_pkt + * @return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. + */ +NMI_API sint8 m2m_wifi_set_receive_buffer(void* pvBuffer,uint16 u16BufferLen); +/**@}*/ +#endif /* ETH_MODE */ +/** @defgroup GetPrngBytes m2m_wifi_prng_get_random_bytes + * @ingroup WLANAPI + * Asynchronous function for retrieving from the firmware a pseudo-random set of bytes as specifed in the size passed in as a parameter. + * The registered wifi-cb function retrieves the random bytes through the response @ref M2M_WIFI_RESP_GET_PRNG + *@{*/ +/*! + * @fn sint8 m2m_wifi_prng_get_random_bytes(uint8 * pu8PRNGBuff,uint16 u16PRNGSize) + * @param [out] pu8PrngBuff + * Pointer to a buffer to receive data. + * @param [in] u16PrngSize + * Request size in bytes + *@warning Size greater than the maximum specified (@ref M2M_BUFFER_MAX_SIZE - sizeof(tstrPrng)) + * causes a negative error @ref M2M_ERR_FAIL. + *@see tstrPrng + * @return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. + */ +sint8 m2m_wifi_prng_get_random_bytes(uint8 * pu8PrngBuff,uint16 u16PrngSize); +/**@}*/ +#ifdef __cplusplus +} +#endif +#endif /* __M2M_WIFI_H__ */ + diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/m2m_ate_mode.c b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/m2m_ate_mode.c new file mode 100644 index 0000000000000..beb1af8052467 --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/m2m_ate_mode.c @@ -0,0 +1,826 @@ +/** + * + * \file + * + * \brief NMC1500 Peripherials Application Interface. + * + * Copyright (c) 2016-2017 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + +#ifdef _M2M_ATE_FW_ +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +INCLUDES +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ +#include "driver/include/m2m_ate_mode.h" +#include "driver/source/nmasic.h" +#include "driver/source/nmdrv.h" +#include "m2m_hif.h" +#include "driver/source/nmbus.h" +#include "bsp/include/nm_bsp.h" + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +MACROS +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ +#define rInterrupt_CORTUS_0 (0x10a8) +#define rInterrupt_CORTUS_1 (0x10ac) +#define rInterrupt_CORTUS_2 (0x10b0) + +#define rBurstTx_NMI_TX_RATE (0x161d00) +#define rBurstTx_NMI_NUM_TX_FRAMES (0x161d04) +#define rBurstTx_NMI_TX_FRAME_LEN (0x161d08) +#define rBurstTx_NMI_TX_CW_PARAM (0x161d0c) +#define rBurstTx_NMI_TX_GAIN (0x161d10) +#define rBurstTx_NMI_TX_DPD_CTRL (0x161d14) +#define rBurstTx_NMI_USE_PMU (0x161d18) +#define rBurstTx_NMI_TEST_CH (0x161d1c) +#define rBurstTx_NMI_TX_PHY_CONT (0x161d20) +#define rBurstTx_NMI_TX_CW_MODE (0x161d24) +#define rBurstTx_NMI_TEST_XO_OFF (0x161d28) +#define rBurstTx_NMI_USE_EFUSE_XO_OFF (0x161d2c) + +#define rBurstTx_NMI_MAC_FILTER_ENABLE_DA (0x161d30) +#define rBurstTx_NMI_MAC_ADDR_LO_PEER (0x161d34) +#define rBurstTx_NMI_MAC_ADDR_LO_SELF (0x161d38) +#define rBurstTx_NMI_MAC_ADDR_HI_PEER (0x161d3c) +#define rBurstTx_NMI_MAC_ADDR_HI_SELF (0x161d40) +#define rBurstTx_NMI_RX_PKT_CNT_SUCCESS (0x161d44) +#define rBurstTx_NMI_RX_PKT_CNT_FAIL (0x161d48) +#define rBurstTx_NMI_SET_SELF_MAC_ADDR (0x161d4c) +#define rBurstTx_NMI_MAC_ADDR_LO_SA (0x161d50) +#define rBurstTx_NMI_MAC_ADDR_HI_SA (0x161d54) +#define rBurstTx_NMI_MAC_FILTER_ENABLE_SA (0x161d58) + +#define rBurstRx_NMI_RX_ALL_PKTS_CONT (0x9898) +#define rBurstRx_NMI_RX_ERR_PKTS_CONT (0x988c) + +#define TX_DGAIN_MAX_NUM_REGS (4) +#define TX_DGAIN_REG_BASE_ADDRESS (0x1240) +#define TX_GAIN_CODE_MAX_NUM_REGS (3) +#define TX_GAIN_CODE_BASE_ADDRESS (0x1250) +#define TX_PA_MAX_NUM_REGS (3) +#define TX_PA_BASE_ADDRESS (0x1e58) +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +VARIABLES +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ +volatile static uint8 gu8AteIsRunning = 0; /*!< ATE firmware status, 1 means ATE is running otherwise stopped */ +volatile static uint8 gu8RxState = 0; /*!< RX status, 1 means Rx is running otherwise stopped */ +volatile static uint8 gu8TxState = 0; /*!< TX status, 1 means Tx is running otherwise stopped */ +volatile static uint32 gaAteFwTxRates[M2M_ATE_MAX_NUM_OF_RATES] = +{ + 0x01, 0x02, 0x05, 0x0B, /*B-Rats*/ + 0x06, 0x09, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x36, /*G-Rats*/ + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87 /*N-Rats*/ +}; + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +STATIC FUNCTIONS +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ +static void m2m_ate_set_rx_status(uint8 u8Value) +{ + gu8RxState = u8Value; +} + +static void m2m_ate_set_tx_status(uint8 u8Value) +{ + gu8TxState = u8Value; +} + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +FUNCTION IMPLEMENTATION +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ +/*! +@fn \ + sint8 m2m_ate_init(void); + +@brief + This function used to download ATE firmware from flash and start it + +@return + The function SHALL return 0 for success and a negative value otherwise. +*/ +sint8 m2m_ate_init(void) +{ + sint8 s8Ret = M2M_SUCCESS; + uint8 u8WifiMode = M2M_WIFI_MODE_ATE_HIGH; + + s8Ret = nm_drv_init(&u8WifiMode); + + return s8Ret; +} + +/*! +@fn \ + sint8 m2m_ate_init(tstrM2mAteInit *pstrInit); + +@brief + This function used to download ATE firmware from flash and start it + +@return + The function SHALL return 0 for success and a negative value otherwise. +*/ +sint8 m2m_ate_init_param(tstrM2mAteInit *pstrInit) +{ + sint8 s8Ret = M2M_SUCCESS; + + s8Ret = nm_drv_init((void*)&pstrInit->u8RxPwrMode); + + return s8Ret; +} + +/*! +@fn \ + sint8 m2m_ate_deinit(void); + +@brief + De-Initialization of ATE firmware mode + +@return + The function SHALL return 0 for success and a negative value otherwise. +*/ +sint8 m2m_ate_deinit(void) +{ + return nm_drv_deinit(NULL); +} + +/*! +@fn \ + sint8 m2m_ate_set_fw_state(uint8); + +@brief + This function used to change ATE firmware status from running to stopped or vice versa. + +@param [in] u8State + Required state of ATE firmware, one of \ref tenuM2mAteFwState enumeration values. +@return + The function SHALL return 0 for success and a negative value otherwise. +\sa + m2m_ate_init +*/ +sint8 m2m_ate_set_fw_state(uint8 u8State) +{ + sint8 s8Ret = M2M_SUCCESS; + uint32_t u32Val = 0; + + if((M2M_ATE_FW_STATE_STOP == u8State) && (M2M_ATE_FW_STATE_STOP != gu8AteIsRunning)) + { + u32Val = nm_read_reg(rNMI_GLB_RESET); + u32Val &= ~(1 << 10); + s8Ret = nm_write_reg(rNMI_GLB_RESET, u32Val); + gu8AteIsRunning = M2M_ATE_FW_STATE_STOP; + } + else if((M2M_ATE_FW_STATE_RUN == u8State) && (M2M_ATE_FW_STATE_RUN != gu8AteIsRunning)) + { + /* 0x1118[0]=0 at power-on-reset: pad-based control. */ + /* Switch cortus reset register to register control. 0x1118[0]=1. */ + u32Val = nm_read_reg(rNMI_BOOT_RESET_MUX); + u32Val |= (1 << 0); + s8Ret = nm_write_reg(rNMI_BOOT_RESET_MUX, u32Val); + if(M2M_SUCCESS != s8Ret) + { + goto __EXIT; + } + /** + Write the firmware download complete magic value 0x10ADD09E at + location 0xFFFF000C (Cortus map) or C000C (AHB map). + This will let the boot-rom code execute from RAM. + **/ + s8Ret = nm_write_reg(0xc0000, 0x71); + if(M2M_SUCCESS != s8Ret) + { + goto __EXIT; + } + + u32Val = nm_read_reg(rNMI_GLB_RESET); + if((u32Val & (1ul << 10)) == (1ul << 10)) + { + u32Val &= ~(1ul << 10); + s8Ret = nm_write_reg(rNMI_GLB_RESET, u32Val); + if(M2M_SUCCESS != s8Ret) + { + goto __EXIT; + } + } + + u32Val |= (1ul << 10); + s8Ret = nm_write_reg(rNMI_GLB_RESET, u32Val); + if(M2M_SUCCESS != s8Ret) + { + goto __EXIT; + } + gu8AteIsRunning = M2M_ATE_FW_STATE_RUN; + } + else + { + s8Ret = M2M_ATE_ERR_UNHANDLED_CASE; + } + +__EXIT: + if((M2M_SUCCESS == s8Ret) && (M2M_ATE_FW_STATE_RUN == gu8AteIsRunning)) + { + nm_bsp_sleep(500); /*wait for ATE firmware start up*/ + } + return s8Ret; +} + +/*! +@fn \ + sint8 m2m_ate_get_fw_state(uint8); + +@brief + This function used to return status of ATE firmware. + +@return + The function SHALL return status of ATE firmware, one of \ref tenuM2mAteFwState enumeration values. +\sa + m2m_ate_init, m2m_ate_set_fw_state +*/ +sint8 m2m_ate_get_fw_state(void) +{ + return gu8AteIsRunning; +} + +/*! +@fn \ + uint32 m2m_ate_get_tx_rate(uint8); + +@brief + This function used to return value of TX rate required by application developer. + +@param [in] u8Index + Index of required rate , one of \ref tenuM2mAteTxIndexOfRates enumeration values. +@return + The function SHALL return 0 for in case of failure otherwise selected rate value. +\sa + tenuM2mAteTxIndexOfRates +*/ +uint32 m2m_ate_get_tx_rate(uint8 u8Index) +{ + if(M2M_ATE_MAX_NUM_OF_RATES <= u8Index) + { + return 0; + } + return gaAteFwTxRates[u8Index]; +} + +/*! +@fn \ + sint8 m2m_ate_get_tx_status(void); + +@brief + This function used to return status of TX test case either running or stopped. + +@return + The function SHALL return status of ATE firmware, 1 if TX is running otherwise 0. +\sa + m2m_ate_start_tx, m2m_ate_stop_tx +*/ +sint8 m2m_ate_get_tx_status(void) +{ + return gu8TxState; +} + +/*! +@fn \ + sint8 m2m_ate_start_tx(tstrM2mAteTx *) + +@brief + This function used to start TX test case. + +@param [in] strM2mAteTx + Type of \ref tstrM2mAteTx, with the values required to enable TX test case. You must use \ref m2m_ate_init first. +@return + The function SHALL return 0 for success and a negative value otherwise. +\sa + m2m_ate_init, m2m_ate_stop_tx, m2m_ate_get_tx_status +*/ +sint8 m2m_ate_start_tx(tstrM2mAteTx * strM2mAteTx) +{ + sint8 s8Ret = M2M_SUCCESS; + uint8 u8LoopCntr = 0; + uint32_t val32; + + + if(NULL == strM2mAteTx) + { + s8Ret = M2M_ATE_ERR_VALIDATE; + goto __EXIT; + } + + if(0 != m2m_ate_get_tx_status()) + { + s8Ret = M2M_ATE_ERR_TX_ALREADY_RUNNING; + goto __EXIT; + } + + if(0 != m2m_ate_get_rx_status()) + { + s8Ret = M2M_ATE_ERR_RX_ALREADY_RUNNING; + goto __EXIT; + } + + if( (strM2mAteTx->channel_num < M2M_ATE_CHANNEL_1) || + (strM2mAteTx->channel_num > M2M_ATE_CHANNEL_14) || + (strM2mAteTx->tx_gain_sel < M2M_ATE_TX_GAIN_DYNAMIC) || + (strM2mAteTx->tx_gain_sel > M2M_ATE_TX_GAIN_TELEC) || + (strM2mAteTx->frame_len > M2M_ATE_MAX_FRAME_LENGTH) || + (strM2mAteTx->frame_len < M2M_ATE_MIN_FRAME_LENGTH) + ) + { + s8Ret = M2M_ATE_ERR_VALIDATE; + goto __EXIT; + } + + if( (strM2mAteTx->duty_cycle < M2M_ATE_TX_DUTY_MAX_VALUE /*1*/) || + (strM2mAteTx->duty_cycle > M2M_ATE_TX_DUTY_MIN_VALUE /*10*/ ) || + (strM2mAteTx->dpd_ctrl < M2M_ATE_TX_DPD_DYNAMIC) || + (strM2mAteTx->dpd_ctrl > M2M_ATE_TX_DPD_ENABLED) || + (strM2mAteTx->use_pmu > M2M_ATE_PMU_ENABLE) || + (strM2mAteTx->phy_burst_tx < M2M_ATE_TX_SRC_MAC) || + (strM2mAteTx->phy_burst_tx > M2M_ATE_TX_SRC_PHY) || + (strM2mAteTx->cw_tx < M2M_ATE_TX_MODE_NORM) || + (strM2mAteTx->cw_tx > M2M_ATE_TX_MODE_CW) + ) + { + s8Ret = M2M_ATE_ERR_VALIDATE; + goto __EXIT; + } + + for(u8LoopCntr=0; u8LoopCntrdata_rate) + { + break; + } + } + + if(M2M_ATE_MAX_NUM_OF_RATES == u8LoopCntr) + { + s8Ret = M2M_ATE_ERR_VALIDATE; + goto __EXIT; + } + + + + s8Ret += nm_write_reg(rBurstTx_NMI_USE_PMU, strM2mAteTx->use_pmu); + s8Ret += nm_write_reg(rBurstTx_NMI_TX_PHY_CONT, strM2mAteTx->phy_burst_tx); + s8Ret += nm_write_reg(rBurstTx_NMI_NUM_TX_FRAMES, strM2mAteTx->num_frames); + s8Ret += nm_write_reg(rBurstTx_NMI_TX_GAIN, strM2mAteTx->tx_gain_sel); + s8Ret += nm_write_reg(rBurstTx_NMI_TEST_CH, strM2mAteTx->channel_num); + s8Ret += nm_write_reg(rBurstTx_NMI_TX_FRAME_LEN, strM2mAteTx->frame_len); + s8Ret += nm_write_reg(rBurstTx_NMI_TX_CW_PARAM, strM2mAteTx->duty_cycle); + s8Ret += nm_write_reg(rBurstTx_NMI_TX_DPD_CTRL, strM2mAteTx->dpd_ctrl); + s8Ret += nm_write_reg(rBurstTx_NMI_TX_RATE, strM2mAteTx->data_rate); + s8Ret += nm_write_reg(rBurstTx_NMI_TX_CW_MODE, strM2mAteTx->cw_tx); + s8Ret += nm_write_reg(rBurstTx_NMI_TEST_XO_OFF, strM2mAteTx->xo_offset_x1000); + s8Ret += nm_write_reg(rBurstTx_NMI_USE_EFUSE_XO_OFF, strM2mAteTx->use_efuse_xo_offset); + + val32 = strM2mAteTx->peer_mac_addr[5] << 0; + val32 |= strM2mAteTx->peer_mac_addr[4] << 8; + val32 |= strM2mAteTx->peer_mac_addr[3] << 16; + nm_write_reg(rBurstTx_NMI_MAC_ADDR_LO_PEER, val32 ); + + val32 = strM2mAteTx->peer_mac_addr[2] << 0; + val32 |= strM2mAteTx->peer_mac_addr[1] << 8; + val32 |= strM2mAteTx->peer_mac_addr[0] << 16; + nm_write_reg(rBurstTx_NMI_MAC_ADDR_HI_PEER, val32 ); + + if(M2M_SUCCESS == s8Ret) + { + s8Ret += nm_write_reg(rInterrupt_CORTUS_0, 1); /*Interrupt Cortus*/ + m2m_ate_set_tx_status(1); + nm_bsp_sleep(200); /*Recommended*/ + } + +__EXIT: + return s8Ret; +} + +/*! +@fn \ + sint8 m2m_ate_stop_tx(void) + +@brief + This function used to stop TX test case. + +@return + The function SHALL return 0 for success and a negative value otherwise. +\sa + m2m_ate_init, m2m_ate_start_tx, m2m_ate_get_tx_status +*/ +sint8 m2m_ate_stop_tx(void) +{ + sint8 s8Ret = M2M_SUCCESS; + + s8Ret = nm_write_reg(rInterrupt_CORTUS_1, 1); + if(M2M_SUCCESS == s8Ret) + { + m2m_ate_set_tx_status(0); + } + + return s8Ret; +} + +/*! +@fn \ + sint8 m2m_ate_get_rx_status(uint8); + +@brief + This function used to return status of RX test case either running or stopped. + +@return + The function SHALL return status of ATE firmware, 1 if RX is running otherwise 0. +\sa + m2m_ate_start_rx, m2m_ate_stop_rx +*/ +sint8 m2m_ate_get_rx_status(void) +{ + return gu8RxState; +} + +/*! +@fn \ + sint8 m2m_ate_start_rx(tstrM2mAteRx *) + +@brief + This function used to start RX test case. + +@param [in] strM2mAteRx + Type of \ref tstrM2mAteRx, with the values required to enable RX test case. You must use \ref m2m_ate_init first. +@return + The function SHALL return 0 for success and a negative value otherwise. +\sa + m2m_ate_init, m2m_ate_stop_rx, m2m_ate_get_rx_status +*/ +sint8 m2m_ate_start_rx(tstrM2mAteRx * strM2mAteRxStr) +{ + sint8 s8Ret = M2M_SUCCESS; + uint32 val32; + if(NULL == strM2mAteRxStr) + { + s8Ret = M2M_ATE_ERR_VALIDATE; + goto __EXIT; + } + + if(0 != m2m_ate_get_tx_status()) + { + s8Ret = M2M_ATE_ERR_TX_ALREADY_RUNNING; + goto __EXIT; + } + + if(0 != m2m_ate_get_rx_status()) + { + s8Ret = M2M_ATE_ERR_RX_ALREADY_RUNNING; + goto __EXIT; + } + + if( (strM2mAteRxStr->channel_num < M2M_ATE_CHANNEL_1) || + (strM2mAteRxStr->channel_num > M2M_ATE_CHANNEL_14)|| + (strM2mAteRxStr->use_pmu > M2M_ATE_PMU_ENABLE) + ) + { + s8Ret = M2M_ATE_ERR_VALIDATE; + goto __EXIT; + } + + s8Ret += nm_write_reg(rBurstTx_NMI_TEST_CH, strM2mAteRxStr->channel_num); + s8Ret += nm_write_reg(rBurstTx_NMI_USE_PMU, strM2mAteRxStr->use_pmu); + s8Ret += nm_write_reg(rBurstTx_NMI_TEST_XO_OFF, strM2mAteRxStr->xo_offset_x1000); + s8Ret += nm_write_reg(rBurstTx_NMI_USE_EFUSE_XO_OFF, strM2mAteRxStr->use_efuse_xo_offset); + + if(strM2mAteRxStr->override_self_mac_addr) + { + val32 = strM2mAteRxStr->self_mac_addr[5] << 0; + val32 |= strM2mAteRxStr->self_mac_addr[4] << 8; + val32 |= strM2mAteRxStr->self_mac_addr[3] << 16; + nm_write_reg(rBurstTx_NMI_MAC_ADDR_LO_SELF, val32 ); + + val32 = strM2mAteRxStr->self_mac_addr[2] << 0; + val32 |= strM2mAteRxStr->self_mac_addr[1] << 8; + val32 |= strM2mAteRxStr->self_mac_addr[0] << 16; + nm_write_reg(rBurstTx_NMI_MAC_ADDR_HI_SELF, val32 ); + } + + if(strM2mAteRxStr->mac_filter_en_sa) + { + val32 = strM2mAteRxStr->peer_mac_addr[5] << 0; + val32 |= strM2mAteRxStr->peer_mac_addr[4] << 8; + val32 |= strM2mAteRxStr->peer_mac_addr[3] << 16; + nm_write_reg(rBurstTx_NMI_MAC_ADDR_LO_SA, val32 ); + + val32 = strM2mAteRxStr->peer_mac_addr[2] << 0; + val32 |= strM2mAteRxStr->peer_mac_addr[1] << 8; + val32 |= strM2mAteRxStr->peer_mac_addr[0] << 16; + nm_write_reg(rBurstTx_NMI_MAC_ADDR_HI_SA, val32 ); + } + + nm_write_reg(rBurstTx_NMI_MAC_FILTER_ENABLE_DA, strM2mAteRxStr->mac_filter_en_da); + nm_write_reg(rBurstTx_NMI_MAC_FILTER_ENABLE_SA, strM2mAteRxStr->mac_filter_en_sa); + nm_write_reg(rBurstTx_NMI_SET_SELF_MAC_ADDR, strM2mAteRxStr->override_self_mac_addr); + + if(M2M_SUCCESS == s8Ret) + { + s8Ret += nm_write_reg(rInterrupt_CORTUS_2, 1); /*Interrupt Cortus*/ + m2m_ate_set_rx_status(1); + nm_bsp_sleep(10); /*Recommended*/ + } + +__EXIT: + return s8Ret; +} + +/*! +@fn \ + sint8 m2m_ate_stop_rx(void) + +@brief + This function used to stop RX test case. + +@return + The function SHALL return 0 for success and a negative value otherwise. +\sa + m2m_ate_init, m2m_ate_start_rx, m2m_ate_get_rx_status +*/ +sint8 m2m_ate_stop_rx(void) +{ + m2m_ate_set_rx_status(0); + nm_bsp_sleep(200); /*Recommended*/ + return M2M_SUCCESS; +} + +/*! +@fn \ + sint8 m2m_ate_read_rx_status(tstrM2mAteRxStatus *) + +@brief + This function used to read RX statistics from ATE firmware. + +@param [out] strM2mAteRxStatus + Type of \ref tstrM2mAteRxStatus used to save statistics of RX test case. You must use \ref m2m_ate_start_rx first. +@return + The function SHALL return 0 for success and a negative value otherwise. +\sa + m2m_ate_init, m2m_ate_start_rx +*/ +sint8 m2m_ate_read_rx_status(tstrM2mAteRxStatus *strM2mAteRxStatus) +{ + sint8 s8Ret = M2M_SUCCESS; + + if(NULL == strM2mAteRxStatus) + { + s8Ret = M2M_ATE_ERR_VALIDATE; + goto __EXIT; + } + + if(0 != m2m_ate_get_tx_status()) + { + s8Ret = M2M_ATE_ERR_TX_ALREADY_RUNNING; + goto __EXIT; + } + + if (nm_read_reg(rBurstTx_NMI_MAC_FILTER_ENABLE_DA) || nm_read_reg(rBurstTx_NMI_MAC_FILTER_ENABLE_SA)) + { + strM2mAteRxStatus->num_rx_pkts = nm_read_reg(rBurstTx_NMI_RX_PKT_CNT_SUCCESS) + nm_read_reg(rBurstTx_NMI_RX_PKT_CNT_FAIL); + strM2mAteRxStatus->num_good_pkts = nm_read_reg(rBurstTx_NMI_RX_PKT_CNT_SUCCESS); + strM2mAteRxStatus->num_err_pkts = nm_read_reg(rBurstTx_NMI_RX_PKT_CNT_FAIL); + } + else + { + strM2mAteRxStatus->num_rx_pkts = nm_read_reg(rBurstRx_NMI_RX_ALL_PKTS_CONT) + nm_read_reg(0x989c); + strM2mAteRxStatus->num_err_pkts = nm_read_reg(rBurstRx_NMI_RX_ERR_PKTS_CONT); + strM2mAteRxStatus->num_good_pkts = strM2mAteRxStatus->num_rx_pkts - strM2mAteRxStatus->num_err_pkts; + } + +__EXIT: + return s8Ret; +} +/*! +@fn \ + sint8 m2m_ate_set_dig_gain(double dGaindB) + +@brief + This function is used to set the digital gain + +@param [in] double dGaindB + The digital gain value required to be set. +@return + The function SHALL return 0 for success and a negative value otherwise. +*/ +sint8 m2m_ate_set_dig_gain(double dGaindB) +{ + uint32_t dGain, val32; + dGain = (uint32_t)(pow(10, dGaindB/20.0) * 1024.0); + + val32 = nm_read_reg(0x160cd0); + val32 &= ~(0x1ffful << 0); + val32 |= (((uint32_t)dGain) << 0); + nm_write_reg(0x160cd0, val32); + return M2M_SUCCESS; +} +/*! +@fn \ + sint8 m2m_ate_get_dig_gain(double * dGaindB) + +@brief + This function is used to get the digital gain + +@param [out] double * dGaindB + The retrieved digital gain value obtained from HW registers in dB. +@return + The function SHALL return 0 for success and a negative value otherwise. +*/ +sint8 m2m_ate_get_dig_gain(double * dGaindB) +{ + uint32 dGain, val32; + + if(!dGaindB) return M2M_ERR_INVALID_ARG; + + val32 = nm_read_reg(0x160cd0); + + dGain = (val32 >> 0) & 0x1ffful; + *dGaindB = 20.0*log10((double)dGain / 1024.0); + + return M2M_SUCCESS; +} +/*! +@fn \ + void m2m_ate_set_pa_gain(uint8 gain_db) + +@brief + This function is used to set the PA gain (18/15/12/9/6/3/0 only) + +@param [in] uint8 gain_db + PA gain level allowed (18/15/12/9/6/3/0 only) + +*/ +void m2m_ate_set_pa_gain(uint8 gain_db) +{ + uint32 PA_1e9c; + uint8 aGain[] = { + /* "0 dB" */ 0x00, + /* "3 dB" */ 0x01, + /* "6 dB" */ 0x03, + /* "9 dB" */ 0x07, + /* "12 dB" */ 0x0f, + /* "15 dB" */ 0x1f, + /* "18 dB" */ 0x3f }; + /* The variable PA gain is valid only for High power mode */ + PA_1e9c = nm_read_reg(0x1e9c); + /* TX bank 0. */ + PA_1e9c &= ~(0x3ful << 8); + PA_1e9c |= (((uint32)aGain[gain_db/3] & 0x3f) << 8); + nm_write_reg(0x1e9c, PA_1e9c); +} +/*! +@fn \ + sint8 m2m_ate_get_pa_gain(double *paGaindB) + +@brief + This function is used to get the PA gain + +@param [out] double *paGaindB + The retrieved PA gain value obtained from HW registers in dB. +@return + The function SHALL return 0 for success and a negative value otherwise. +*/ +sint8 m2m_ate_get_pa_gain(double *paGaindB) +{ + uint32 val32, paGain; + uint32 m_cmbPAGainStep; + + if(!paGaindB) + return M2M_ERR_INVALID_ARG; + + val32 = nm_read_reg(0x1e9c); + + paGain = (val32 >> 8) & 0x3f; + + switch(paGain){ + case 0x1: + m_cmbPAGainStep = 5; + break; + case 0x3: + m_cmbPAGainStep = 4; + break; + case 0x7: + m_cmbPAGainStep = 3; + break; + case 0xf: + m_cmbPAGainStep = 2; + break; + case 0x1f: + m_cmbPAGainStep = 1; + break; + case 0x3f: + m_cmbPAGainStep = 0; + break; + default: + m_cmbPAGainStep = 0; + break; + } + + *paGaindB = 18 - m_cmbPAGainStep*3; + + return M2M_SUCCESS; +} +/*! +@fn \ + sint8 m2m_ate_get_ppa_gain(double * ppaGaindB) + +@brief + This function is used to get the PPA gain + +@param [out] uint32 * ppaGaindB + The retrieved PPA gain value obtained from HW registers in dB. +@return + The function SHALL return 0 for success and a negative value otherwise. +*/ +sint8 m2m_ate_get_ppa_gain(double * ppaGaindB) +{ + uint32 val32, ppaGain, m_cmbPPAGainStep; + + if(!ppaGaindB) return M2M_ERR_INVALID_ARG; + + val32 = nm_read_reg(0x1ea0); + + ppaGain = (val32 >> 5) & 0x7; + + switch(ppaGain){ + case 0x1: + m_cmbPPAGainStep = 2; + break; + case 0x3: + m_cmbPPAGainStep = 1; + break; + case 0x7: + m_cmbPPAGainStep = 0; + break; + default: + m_cmbPPAGainStep = 3; + break; + } + + *ppaGaindB = 9 - m_cmbPPAGainStep*3; + + + return M2M_SUCCESS; +} +/*! +@fn \ + sint8 m2m_ate_get_tot_gain(double * totGaindB) + +@brief + This function is used to calculate the total gain + +@param [out] double * totGaindB + The retrieved total gain value obtained from calculations made based on the digital gain, PA and PPA gain values. +@return + The function SHALL return 0 for success and a negative value otherwise. +*/ +sint8 m2m_ate_get_tot_gain(double * totGaindB) +{ + double dGaindB, paGaindB, ppaGaindB; + + if(!totGaindB) return M2M_ERR_INVALID_ARG; + + m2m_ate_get_pa_gain(&paGaindB); + m2m_ate_get_ppa_gain(&ppaGaindB); + m2m_ate_get_dig_gain(&dGaindB); + + *totGaindB = dGaindB + paGaindB + ppaGaindB; + + return M2M_SUCCESS; +} + +#endif //_M2M_ATE_FW_ \ No newline at end of file diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/m2m_crypto.c b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/m2m_crypto.c new file mode 100644 index 0000000000000..9ac7711309552 --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/m2m_crypto.c @@ -0,0 +1,1010 @@ +/** + * + * \file + * + * \brief WINC Crypto module. + * + * Copyright (c) 2016 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +INCLUDES +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ + +#include "driver/include/m2m_crypto.h" +#include "driver/source/nmbus.h" +#include "driver/source/nmasic.h" + +#ifdef CONF_CRYPTO_HW + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +MACROS +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ + +/*======*======*======*======*======*=======* +* WINC SHA256 HW Engine Register Definition * +*======*======*======*======*======*========*/ + +#define SHA_BLOCK_SIZE (64) + +#define SHARED_MEM_BASE (0xd0000) + + +#define SHA256_MEM_BASE (0x180000UL) +#define SHA256_ENGINE_ADDR (0x180000ul) + +/* SHA256 Registers */ +#define SHA256_CTRL (SHA256_MEM_BASE+0x00) +#define SHA256_CTRL_START_CALC_MASK (NBIT0) +#define SHA256_CTRL_START_CALC_SHIFT (0) +#define SHA256_CTRL_PREPROCESS_MASK (NBIT1) +#define SHA256_CTRL_PREPROCESS_SHIFT (1) +#define SHA256_CTRL_HASH_HASH_MASK (NBIT2) +#define SHA256_CTRL_HASH_HASH_SHIFT (2) +#define SHA256_CTRL_INIT_SHA256_STATE_MASK (NBIT3) +#define SHA256_CTRL_INIT_SHA256_STATE_SHIFT (3) +#define SHA256_CTRL_WR_BACK_HASH_VALUE_MASK (NBIT4) +#define SHA256_CTRL_WR_BACK_HASH_VALUE_SHIFT (4) +#define SHA256_CTRL_FORCE_SHA256_QUIT_MASK (NBIT5) +#define SHA256_CTRL_FORCE_SHA256_QUIT_SHIFT (5) + +#define SHA256_REGS_SHA256_CTRL_AHB_BYTE_REV_EN (NBIT6) +#define SHA256_REGS_SHA256_CTRL_RESERVED (NBIT7) +#define SHA256_REGS_SHA256_CTRL_CORE_TO_AHB_CLK_RATIO (NBIT8+ NBIT9+ NBIT10) +#define SHA256_REGS_SHA256_CTRL_CORE_TO_AHB_CLK_RATIO_MASK (NBIT2+ NBIT1+ NBIT0) +#define SHA256_REGS_SHA256_CTRL_CORE_TO_AHB_CLK_RATIO_SHIFT (8) +#define SHA256_REGS_SHA256_CTRL_RESERVED_11 (NBIT11) +#define SHA256_REGS_SHA256_CTRL_SHA1_CALC (NBIT12) +#define SHA256_REGS_SHA256_CTRL_PBKDF2_SHA1_CALC (NBIT13) + + +#define SHA256_START_RD_ADDR (SHA256_MEM_BASE+0x04UL) +#define SHA256_DATA_LENGTH (SHA256_MEM_BASE+0x08UL) +#define SHA256_START_WR_ADDR (SHA256_MEM_BASE+0x0cUL) +#define SHA256_COND_CHK_CTRL (SHA256_MEM_BASE+0x10) +#define SHA256_COND_CHK_CTRL_HASH_VAL_COND_CHK_MASK (NBIT1 | NBIT0) +#define SHA256_COND_CHK_CTRL_HASH_VAL_COND_CHK_SHIFT (0) +#define SHA256_COND_CHK_CTRL_STEP_VAL_MASK (NBIT6 | NBIT5 | NBIT4 | NBIT3 | NBIT2) +#define SHA256_COND_CHK_CTRL_STEP_VAL_SHIFT (2) +#define SHA256_COND_CHK_CTRL_COND_CHK_RESULT_MASK (NBIT7) +#define SHA256_COND_CHK_CTRL_COND_CHK_RESULT_SHIFT (7) + +#define SHA256_MOD_DATA_RANGE (SHA256_MEM_BASE+0x14) +#define SHA256_MOD_DATA_RANGE_ST_BYTE_2_ADD_STP_MASK (NBIT24-1) +#define SHA256_MOD_DATA_RANGE_ST_BYTE_2_ADD_STP_SHIFT (0) +#define SHA256_MOD_DATA_RANGE_MOD_DATA_LEN_MASK (NBIT24 | NBIT25| NBIT26) +#define SHA256_MOD_DATA_RANGE_MOD_DATA_LEN_SHIFT (24) + + +#define SHA256_COND_CHK_STS_1 (SHA256_MEM_BASE+0x18) +#define SHA256_COND_CHK_STS_2 (SHA256_MEM_BASE+0x1c) +#define SHA256_DONE_INTR_ENABLE (SHA256_MEM_BASE+0x20) +#define SHA256_DONE_INTR_STS (SHA256_MEM_BASE+0x24) +#define SHA256_TARGET_HASH_H1 (SHA256_MEM_BASE+0x28) +#define SHA256_TARGET_HASH_H2 (SHA256_MEM_BASE+0x2c) +#define SHA256_TARGET_HASH_H3 (SHA256_MEM_BASE+0x30) +#define SHA256_TARGET_HASH_H4 (SHA256_MEM_BASE+0x34) +#define SHA256_TARGET_HASH_H5 (SHA256_MEM_BASE+0x38) +#define SHA256_TARGET_HASH_H6 (SHA256_MEM_BASE+0x3c) +#define SHA256_TARGET_HASH_H7 (SHA256_MEM_BASE+0x40) +#define SHA256_TARGET_HASH_H8 (SHA256_MEM_BASE+0x44) + +/*======*======*======*======*======*=======* +* WINC BIGINT HW Engine Register Definition * +*======*======*======*======*======*========*/ + + +#define BIGINT_ENGINE_ADDR (0x180080ul) +#define BIGINT_VERSION (BIGINT_ENGINE_ADDR + 0x00) + +#define BIGINT_MISC_CTRL (BIGINT_ENGINE_ADDR + 0x04) +#define BIGINT_MISC_CTRL_CTL_START (NBIT0) +#define BIGINT_MISC_CTRL_CTL_RESET (NBIT1) +#define BIGINT_MISC_CTRL_CTL_MSW_FIRST (NBIT2) +#define BIGINT_MISC_CTRL_CTL_SWAP_BYTE_ORDER (NBIT3) +#define BIGINT_MISC_CTRL_CTL_FORCE_BARRETT (NBIT4) +#define BIGINT_MISC_CTRL_CTL_M_PRIME_VALID (NBIT5) + +#define BIGINT_M_PRIME (BIGINT_ENGINE_ADDR + 0x08) + +#define BIGINT_STATUS (BIGINT_ENGINE_ADDR + 0x0C) +#define BIGINT_STATUS_STS_DONE (NBIT0) + +#define BIGINT_CLK_COUNT (BIGINT_ENGINE_ADDR + 0x10) +#define BIGINT_ADDR_X (BIGINT_ENGINE_ADDR + 0x14) +#define BIGINT_ADDR_E (BIGINT_ENGINE_ADDR + 0x18) +#define BIGINT_ADDR_M (BIGINT_ENGINE_ADDR + 0x1C) +#define BIGINT_ADDR_R (BIGINT_ENGINE_ADDR + 0x20) +#define BIGINT_LENGTH (BIGINT_ENGINE_ADDR + 0x24) + +#define BIGINT_IRQ_STS (BIGINT_ENGINE_ADDR + 0x28) +#define BIGINT_IRQ_STS_DONE (NBIT0) +#define BIGINT_IRQ_STS_CHOOSE_MONT (NBIT1) +#define BIGINT_IRQ_STS_M_READ (NBIT2) +#define BIGINT_IRQ_STS_X_READ (NBIT3) +#define BIGINT_IRQ_STS_START (NBIT4) +#define BIGINT_IRQ_STS_PRECOMP_FINISH (NBIT5) + +#define BIGINT_IRQ_MASK (BIGINT_ENGINE_ADDR + 0x2C) +#define BIGINT_IRQ_MASK_CTL_IRQ_MASK_START (NBIT4) + +#define ENABLE_FLIPPING 1 + + + + +#define GET_UINT32(BUF,OFFSET) (((uint32)((BUF)[OFFSET])) | ((uint32)(((BUF)[OFFSET + 1]) << 8)) | \ +((uint32)(((BUF)[OFFSET + 2]) << 16)) | ((uint32)(((BUF)[OFFSET + 3]) << 24))) + +#define PUTU32(VAL32,BUF,OFFSET) \ +do \ +{ \ + (BUF)[OFFSET ] = BYTE_3((VAL32)); \ + (BUF)[OFFSET +1 ] = BYTE_2((VAL32)); \ + (BUF)[OFFSET +2 ] = BYTE_1((VAL32)); \ + (BUF)[OFFSET +3 ] = BYTE_0((VAL32)); \ +}while(0) + + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +DATA TYPES +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ + +/*! +@struct \ + tstrHashContext + +@brief +*/ +typedef struct{ + uint32 au32HashState[M2M_SHA256_DIGEST_LEN/4]; + uint8 au8CurrentBlock[64]; + uint32 u32TotalLength; + uint8 u8InitHashFlag; +}tstrSHA256HashCtxt; + + + +/*======*======*======*======*======*=======* +* SHA256 IMPLEMENTATION * +*======*======*======*======*======*========*/ + +sint8 m2m_crypto_sha256_hash_init(tstrM2mSha256Ctxt *pstrSha256Ctxt) +{ + tstrSHA256HashCtxt *pstrSHA256 = (tstrSHA256HashCtxt*)pstrSha256Ctxt; + if(pstrSHA256 != NULL) + { + m2m_memset((uint8*)pstrSha256Ctxt, 0, sizeof(tstrM2mSha256Ctxt)); + pstrSHA256->u8InitHashFlag = 1; + } + return 0; +} + +sint8 m2m_crypto_sha256_hash_update(tstrM2mSha256Ctxt *pstrSha256Ctxt, uint8 *pu8Data, uint16 u16DataLength) +{ + sint8 s8Ret = M2M_ERR_FAIL; + tstrSHA256HashCtxt *pstrSHA256 = (tstrSHA256HashCtxt*)pstrSha256Ctxt; + if(pstrSHA256 != NULL) + { + uint32 u32ReadAddr; + uint32 u32WriteAddr = SHARED_MEM_BASE; + uint32 u32Addr = u32WriteAddr; + uint32 u32ResidualBytes; + uint32 u32NBlocks; + uint32 u32Offset; + uint32 u32CurrentBlock = 0; + uint8 u8IsDone = 0; + + /* Get the remaining bytes from the previous update (if the length is not block aligned). */ + u32ResidualBytes = pstrSHA256->u32TotalLength % SHA_BLOCK_SIZE; + + /* Update the total data length. */ + pstrSHA256->u32TotalLength += u16DataLength; + + if(u32ResidualBytes != 0) + { + if((u32ResidualBytes + u16DataLength) >= SHA_BLOCK_SIZE) + { + u32Offset = SHA_BLOCK_SIZE - u32ResidualBytes; + m2m_memcpy(&pstrSHA256->au8CurrentBlock[u32ResidualBytes], pu8Data, u32Offset); + pu8Data += u32Offset; + u16DataLength -= u32Offset; + + nm_write_block(u32Addr, pstrSHA256->au8CurrentBlock, SHA_BLOCK_SIZE); + u32Addr += SHA_BLOCK_SIZE; + u32CurrentBlock = 1; + } + else + { + m2m_memcpy(&pstrSHA256->au8CurrentBlock[u32ResidualBytes], pu8Data, u16DataLength); + u16DataLength = 0; + } + } + + /* Get the number of HASH BLOCKs and the residual bytes. */ + u32NBlocks = u16DataLength / SHA_BLOCK_SIZE; + u32ResidualBytes = u16DataLength % SHA_BLOCK_SIZE; + + if(u32NBlocks != 0) + { + nm_write_block(u32Addr, pu8Data, (uint16)(u32NBlocks * SHA_BLOCK_SIZE)); + pu8Data += (u32NBlocks * SHA_BLOCK_SIZE); + } + + u32NBlocks += u32CurrentBlock; + if(u32NBlocks != 0) + { + uint32 u32RegVal = 0; + + nm_write_reg(SHA256_CTRL, u32RegVal); + u32RegVal |= SHA256_CTRL_FORCE_SHA256_QUIT_MASK; + nm_write_reg(SHA256_CTRL, u32RegVal); + + if(pstrSHA256->u8InitHashFlag) + { + pstrSHA256->u8InitHashFlag = 0; + u32RegVal |= SHA256_CTRL_INIT_SHA256_STATE_MASK; + } + + u32ReadAddr = u32WriteAddr + (u32NBlocks * SHA_BLOCK_SIZE); + nm_write_reg(SHA256_DATA_LENGTH, (u32NBlocks * SHA_BLOCK_SIZE)); + nm_write_reg(SHA256_START_RD_ADDR, u32WriteAddr); + nm_write_reg(SHA256_START_WR_ADDR, u32ReadAddr); + + u32RegVal |= SHA256_CTRL_START_CALC_MASK; + + u32RegVal &= ~(0x7 << 8); + u32RegVal |= (2 << 8); + + nm_write_reg(SHA256_CTRL, u32RegVal); + + /* 5. Wait for done_intr */ + while(!u8IsDone) + { + u32RegVal = nm_read_reg(SHA256_DONE_INTR_STS); + u8IsDone = u32RegVal & NBIT0; + } + } + if(u32ResidualBytes != 0) + { + m2m_memcpy(pstrSHA256->au8CurrentBlock, pu8Data, u32ResidualBytes); + } + s8Ret = M2M_SUCCESS; + } + return s8Ret; +} + + +sint8 m2m_crypto_sha256_hash_finish(tstrM2mSha256Ctxt *pstrSha256Ctxt, uint8 *pu8Sha256Digest) +{ + sint8 s8Ret = M2M_ERR_FAIL; + tstrSHA256HashCtxt *pstrSHA256 = (tstrSHA256HashCtxt*)pstrSha256Ctxt; + if(pstrSHA256 != NULL) + { + uint32 u32ReadAddr; + uint32 u32WriteAddr = SHARED_MEM_BASE; + uint32 u32Addr = u32WriteAddr; + uint16 u16Offset; + uint16 u16PaddingLength; + uint16 u16NBlocks = 1; + uint32 u32RegVal = 0; + uint32 u32Idx,u32ByteIdx; + uint32 au32Digest[M2M_SHA256_DIGEST_LEN / 4]; + uint8 u8IsDone = 0; + + nm_write_reg(SHA256_CTRL,u32RegVal); + u32RegVal |= SHA256_CTRL_FORCE_SHA256_QUIT_MASK; + nm_write_reg(SHA256_CTRL,u32RegVal); + + if(pstrSHA256->u8InitHashFlag) + { + pstrSHA256->u8InitHashFlag = 0; + u32RegVal |= SHA256_CTRL_INIT_SHA256_STATE_MASK; + } + + /* Calculate the offset of the last data byte in the current block. */ + u16Offset = (uint16)(pstrSHA256->u32TotalLength % SHA_BLOCK_SIZE); + + /* Add the padding byte 0x80. */ + pstrSHA256->au8CurrentBlock[u16Offset ++] = 0x80; + + /* Calculate the required padding to complete + one Hash Block Size. + */ + u16PaddingLength = SHA_BLOCK_SIZE - u16Offset; + m2m_memset(&pstrSHA256->au8CurrentBlock[u16Offset], 0, u16PaddingLength); + + /* If the padding count is not enough to hold 64-bit representation of + the total input message length, one padding block is required. + */ + if(u16PaddingLength < 8) + { + nm_write_block(u32Addr, pstrSHA256->au8CurrentBlock, SHA_BLOCK_SIZE); + u32Addr += SHA_BLOCK_SIZE; + m2m_memset(pstrSHA256->au8CurrentBlock, 0, SHA_BLOCK_SIZE); + u16NBlocks ++; + } + + /* pack the length at the end of the padding block */ + PUTU32(pstrSHA256->u32TotalLength << 3, pstrSHA256->au8CurrentBlock, (SHA_BLOCK_SIZE - 4)); + + u32ReadAddr = u32WriteAddr + (u16NBlocks * SHA_BLOCK_SIZE); + nm_write_block(u32Addr, pstrSHA256->au8CurrentBlock, SHA_BLOCK_SIZE); + nm_write_reg(SHA256_DATA_LENGTH, (u16NBlocks * SHA_BLOCK_SIZE)); + nm_write_reg(SHA256_START_RD_ADDR, u32WriteAddr); + nm_write_reg(SHA256_START_WR_ADDR, u32ReadAddr); + + u32RegVal |= SHA256_CTRL_START_CALC_MASK; + u32RegVal |= SHA256_CTRL_WR_BACK_HASH_VALUE_MASK; + u32RegVal &= ~(0x7UL << 8); + u32RegVal |= (0x2UL << 8); + + nm_write_reg(SHA256_CTRL,u32RegVal); + + + /* 5. Wait for done_intr */ + while(!u8IsDone) + { + u32RegVal = nm_read_reg(SHA256_DONE_INTR_STS); + u8IsDone = u32RegVal & NBIT0; + } + nm_read_block(u32ReadAddr, (uint8*)au32Digest, 32); + + /* Convert the output words to an array of bytes. + */ + u32ByteIdx = 0; + for(u32Idx = 0; u32Idx < (M2M_SHA256_DIGEST_LEN / 4); u32Idx ++) + { + pu8Sha256Digest[u32ByteIdx ++] = BYTE_3(au32Digest[u32Idx]); + pu8Sha256Digest[u32ByteIdx ++] = BYTE_2(au32Digest[u32Idx]); + pu8Sha256Digest[u32ByteIdx ++] = BYTE_1(au32Digest[u32Idx]); + pu8Sha256Digest[u32ByteIdx ++] = BYTE_0(au32Digest[u32Idx]); + } + s8Ret = M2M_SUCCESS; + } + return s8Ret; +} + + +/*======*======*======*======*======*=======* +* RSA IMPLEMENTATION * +*======*======*======*======*======*========*/ + +static void FlipBuffer(uint8 *pu8InBuffer, uint8 *pu8OutBuffer, uint16 u16BufferSize) +{ + uint16 u16Idx; + for(u16Idx = 0; u16Idx < u16BufferSize; u16Idx ++) + { +#if ENABLE_FLIPPING == 1 + pu8OutBuffer[u16Idx] = pu8InBuffer[u16BufferSize - u16Idx - 1]; +#else + pu8OutBuffer[u16Idx] = pu8InBuffer[u16Idx]; +#endif + } +} + +void BigInt_ModExp +( + uint8 *pu8X, uint16 u16XSize, + uint8 *pu8E, uint16 u16ESize, + uint8 *pu8M, uint16 u16MSize, + uint8 *pu8R, uint16 u16RSize + ) +{ + uint32 u32Reg; + uint8 au8Tmp[780] = {0}; + uint32 u32XAddr = SHARED_MEM_BASE; + uint32 u32MAddr; + uint32 u32EAddr; + uint32 u32RAddr; + uint8 u8EMswBits = 32; + uint32 u32Mprime = 0x7F; + uint16 u16XSizeWords,u16ESizeWords; + uint32 u32Exponent; + + u16XSizeWords = (u16XSize + 3) / 4; + u16ESizeWords = (u16ESize + 3) / 4; + + u32MAddr = u32XAddr + (u16XSizeWords * 4); + u32EAddr = u32MAddr + (u16XSizeWords * 4); + u32RAddr = u32EAddr + (u16ESizeWords * 4); + + /* Reset the core. + */ + u32Reg = 0; + u32Reg |= BIGINT_MISC_CTRL_CTL_RESET; + u32Reg = nm_read_reg(BIGINT_MISC_CTRL); + u32Reg &= ~BIGINT_MISC_CTRL_CTL_RESET; + u32Reg = nm_read_reg(BIGINT_MISC_CTRL); + + nm_write_block(u32RAddr,au8Tmp, u16RSize); + + /* Write Input Operands to Chip Memory. + */ + /*------- X -------*/ + FlipBuffer(pu8X,au8Tmp,u16XSize); + nm_write_block(u32XAddr,au8Tmp,u16XSizeWords * 4); + + /*------- E -------*/ + m2m_memset(au8Tmp, 0, sizeof(au8Tmp)); + FlipBuffer(pu8E, au8Tmp, u16ESize); + nm_write_block(u32EAddr, au8Tmp, u16ESizeWords * 4); + u32Exponent = GET_UINT32(au8Tmp, (u16ESizeWords * 4) - 4); + while((u32Exponent & NBIT31)== 0) + { + u32Exponent <<= 1; + u8EMswBits --; + } + + /*------- M -------*/ + m2m_memset(au8Tmp, 0, sizeof(au8Tmp)); + FlipBuffer(pu8M, au8Tmp, u16XSize); + nm_write_block(u32MAddr, au8Tmp, u16XSizeWords * 4); + + /* Program the addresses of the input operands. + */ + nm_write_reg(BIGINT_ADDR_X, u32XAddr); + nm_write_reg(BIGINT_ADDR_E, u32EAddr); + nm_write_reg(BIGINT_ADDR_M, u32MAddr); + nm_write_reg(BIGINT_ADDR_R, u32RAddr); + + /* Mprime. + */ + nm_write_reg(BIGINT_M_PRIME,u32Mprime); + + /* Length. + */ + u32Reg = (u16XSizeWords & 0xFF); + u32Reg += ((u16ESizeWords & 0xFF) << 8); + u32Reg += (u8EMswBits << 16); + nm_write_reg(BIGINT_LENGTH,u32Reg); + + /* CTRL Register. + */ + u32Reg = nm_read_reg(BIGINT_MISC_CTRL); + u32Reg ^= BIGINT_MISC_CTRL_CTL_START; + u32Reg |= BIGINT_MISC_CTRL_CTL_FORCE_BARRETT; + //u32Reg |= BIGINT_MISC_CTRL_CTL_M_PRIME_VALID; +#if ENABLE_FLIPPING == 0 + u32Reg |= BIGINT_MISC_CTRL_CTL_MSW_FIRST; +#endif + nm_write_reg(BIGINT_MISC_CTRL,u32Reg); + + /* Wait for computation to complete. */ + while(1) + { + u32Reg = nm_read_reg(BIGINT_IRQ_STS); + if(u32Reg & BIGINT_IRQ_STS_DONE) + { + break; + } + } + nm_write_reg(BIGINT_IRQ_STS,0); + m2m_memset(au8Tmp, 0, sizeof(au8Tmp)); + nm_read_block(u32RAddr, au8Tmp, u16RSize); + FlipBuffer(au8Tmp, pu8R, u16RSize); +} + + + +#define MD5_DIGEST_SIZE (16) +#define SHA1_DIGEST_SIZE (20) + +static const uint8 au8TEncodingMD5[] = +{ + 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, + 0x04 +}; +/*!< Fixed part of the Encoding T for the MD5 hash algorithm. +*/ + + +static const uint8 au8TEncodingSHA1[] = +{ + 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, + 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04 +}; +/*!< Fixed part of the Encoding T for the SHA-1 hash algorithm. +*/ + + +static const uint8 au8TEncodingSHA2[] = +{ + 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, + 0x00, 0x04 +}; +/*!< Fixed part of the Encoding T for the SHA-2 hash algorithm. +*/ + + +sint8 m2m_crypto_rsa_sign_verify(uint8 *pu8N, uint16 u16NSize, uint8 *pu8E, uint16 u16ESize, uint8 *pu8SignedMsgHash, + uint16 u16HashLength, uint8 *pu8RsaSignature) +{ + sint8 s8Ret = M2M_RSA_SIGN_FAIL; + + if((pu8N != NULL) && (pu8E != NULL) && (pu8RsaSignature != NULL) && (pu8SignedMsgHash != NULL)) + { + uint16 u16TLength, u16TEncodingLength; + uint8 *pu8T; + uint8 au8EM[512]; + + /* Selection of correct T Encoding based on the hash size. + */ + if(u16HashLength == MD5_DIGEST_SIZE) + { + pu8T = (uint8*)au8TEncodingMD5; + u16TEncodingLength = sizeof(au8TEncodingMD5); + } + else if(u16HashLength == SHA1_DIGEST_SIZE) + { + pu8T = (uint8*)au8TEncodingSHA1; + u16TEncodingLength = sizeof(au8TEncodingSHA1); + } + else + { + pu8T = (uint8*)au8TEncodingSHA2; + u16TEncodingLength = sizeof(au8TEncodingSHA2); + } + u16TLength = u16TEncodingLength + 1 + u16HashLength; + + /* If emLen < tLen + 11. + */ + if(u16NSize >= (u16TLength + 11)) + { + uint32 u32PSLength,u32Idx = 0; + + /* + RSA verification + */ + BigInt_ModExp(pu8RsaSignature, u16NSize, pu8E, u16ESize, pu8N, u16NSize, au8EM, u16NSize); + + u32PSLength = u16NSize - u16TLength - 3; + + /* + The calculated EM must match the following pattern. + *======*======*======*======*======* + * 0x00 || 0x01 || PS || 0x00 || T * + *======*======*======*======*======* + Where PS is all 0xFF + T is defined based on the hash algorithm. + */ + if((au8EM[0] == 0x00) && (au8EM[1] == 0x01)) + { + for(u32Idx = 2; au8EM[u32Idx] == 0xFF; u32Idx ++); + if(u32Idx == (u32PSLength + 2)) + { + if(au8EM[u32Idx ++] == 0x00) + { + if(!m2m_memcmp(&au8EM[u32Idx], pu8T, u16TEncodingLength)) + { + u32Idx += u16TEncodingLength; + if(au8EM[u32Idx ++] == u16HashLength) + s8Ret = m2m_memcmp(&au8EM[u32Idx], pu8SignedMsgHash, u16HashLength); + } + } + } + } + } + } + return s8Ret; +} + + +sint8 m2m_crypto_rsa_sign_gen(uint8 *pu8N, uint16 u16NSize, uint8 *pu8d, uint16 u16dSize, uint8 *pu8SignedMsgHash, + uint16 u16HashLength, uint8 *pu8RsaSignature) +{ + sint8 s8Ret = M2M_RSA_SIGN_FAIL; + + if((pu8N != NULL) && (pu8d != NULL) && (pu8RsaSignature != NULL) && (pu8SignedMsgHash != NULL)) + { + uint16 u16TLength, u16TEncodingLength; + uint8 *pu8T; + uint8 au8EM[512]; + + /* Selection of correct T Encoding based on the hash size. + */ + if(u16HashLength == MD5_DIGEST_SIZE) + { + pu8T = (uint8*)au8TEncodingMD5; + u16TEncodingLength = sizeof(au8TEncodingMD5); + } + else if(u16HashLength == SHA1_DIGEST_SIZE) + { + pu8T = (uint8*)au8TEncodingSHA1; + u16TEncodingLength = sizeof(au8TEncodingSHA1); + } + else + { + pu8T = (uint8*)au8TEncodingSHA2; + u16TEncodingLength = sizeof(au8TEncodingSHA2); + } + u16TLength = u16TEncodingLength + 1 + u16HashLength; + + /* If emLen < tLen + 11. + */ + if(u16NSize >= (u16TLength + 11)) + { + uint16 u16PSLength = 0; + uint16 u16Offset = 0; + + /* + The calculated EM must match the following pattern. + *======*======*======*======*======* + * 0x00 || 0x01 || PS || 0x00 || T * + *======*======*======*======*======* + Where PS is all 0xFF + T is defined based on the hash algorithm. + */ + au8EM[u16Offset ++] = 0; + au8EM[u16Offset ++] = 1; + u16PSLength = u16NSize - u16TLength - 3; + m2m_memset(&au8EM[u16Offset], 0xFF, u16PSLength); + u16Offset += u16PSLength; + au8EM[u16Offset ++] = 0; + m2m_memcpy(&au8EM[u16Offset], pu8T, u16TEncodingLength); + u16Offset += u16TEncodingLength; + au8EM[u16Offset ++] = u16HashLength; + m2m_memcpy(&au8EM[u16Offset], pu8SignedMsgHash, u16HashLength); + + /* + RSA Signature Generation + */ + BigInt_ModExp(au8EM, u16NSize, pu8d, u16dSize, pu8N, u16NSize, pu8RsaSignature, u16NSize); + s8Ret = M2M_RSA_SIGN_OK; + } + } + return s8Ret; +} + +#endif /* CONF_CRYPTO */ + +#ifdef CONF_CRYPTO_SOFT + +typedef struct { + tpfAppCryproCb pfAppCryptoCb; + uint8 * pu8Digest; + uint8 * pu8Rsa; + uint8 u8CryptoBusy; +}tstrCryptoCtxt; + +typedef struct { + uint8 au8N[M2M_MAX_RSA_LEN]; + uint8 au8E[M2M_MAX_RSA_LEN]; + uint8 au8Hash[M2M_SHA256_DIGEST_LEN]; + uint16 u16Nsz; + uint16 u16Esz; + uint16 u16Hsz; + uint8 _pad16_[2]; +}tstrRsaPayload; + +static tstrCryptoCtxt gstrCryptoCtxt; + + +/** +* @fn m2m_crypto_cb(uint8 u8OpCode, uint16 u16DataSize, uint32 u32Addr) +* @brief WiFi call back function +* @param [in] u8OpCode +* HIF Opcode type. +* @param [in] u16DataSize +* HIF data length. +* @param [in] u32Addr +* HIF address. +* @author +* @date +* @version 1.0 +*/ +static void m2m_crypto_cb(uint8 u8OpCode, uint16 u16DataSize, uint32 u32Addr) +{ + sint8 ret = M2M_SUCCESS; + gstrCryptoCtxt.u8CryptoBusy = 0; + if(u8OpCode == M2M_CRYPTO_RESP_SHA256_INIT) + { + tstrM2mSha256Ctxt strCtxt; + if (hif_receive(u32Addr, (uint8*) &strCtxt,sizeof(tstrM2mSha256Ctxt), 0) == M2M_SUCCESS) + { + tstrCyptoResp strResp; + if(hif_receive(u32Addr + sizeof(tstrM2mSha256Ctxt), (uint8*) &strResp,sizeof(tstrCyptoResp), 1) == M2M_SUCCESS) + { + if (gstrCryptoCtxt.pfAppCryptoCb) + gstrCryptoCtxt.pfAppCryptoCb(u8OpCode,&strResp,&strCtxt); + } + } + } + else if(u8OpCode == M2M_CRYPTO_RESP_SHA256_UPDATE) + { + tstrM2mSha256Ctxt strCtxt; + if (hif_receive(u32Addr, (uint8*) &strCtxt,sizeof(tstrM2mSha256Ctxt), 0) == M2M_SUCCESS) + { + tstrCyptoResp strResp; + if (hif_receive(u32Addr + sizeof(tstrM2mSha256Ctxt), (uint8*) &strResp,sizeof(tstrCyptoResp), 1) == M2M_SUCCESS) + { + if (gstrCryptoCtxt.pfAppCryptoCb) + gstrCryptoCtxt.pfAppCryptoCb(u8OpCode,&strResp,&strCtxt); + } + } + + } + else if(u8OpCode == M2M_CRYPTO_RESP_SHA256_FINSIH) + { + tstrCyptoResp strResp; + if (hif_receive(u32Addr + sizeof(tstrM2mSha256Ctxt), (uint8*) &strResp,sizeof(tstrCyptoResp), 0) == M2M_SUCCESS) + { + if (hif_receive(u32Addr + sizeof(tstrM2mSha256Ctxt) + sizeof(tstrCyptoResp), (uint8*)gstrCryptoCtxt.pu8Digest,M2M_SHA256_DIGEST_LEN, 1) == M2M_SUCCESS) + { + if (gstrCryptoCtxt.pfAppCryptoCb) + gstrCryptoCtxt.pfAppCryptoCb(u8OpCode,&strResp,gstrCryptoCtxt.pu8Digest); + + } + } + } + else if(u8OpCode == M2M_CRYPTO_RESP_RSA_SIGN_GEN) + { + tstrCyptoResp strResp; + if (hif_receive(u32Addr + sizeof(tstrRsaPayload), (uint8*)&strResp,sizeof(tstrCyptoResp), 0) == M2M_SUCCESS) + { + if (hif_receive(u32Addr + sizeof(tstrRsaPayload) + sizeof(tstrCyptoResp), (uint8*)gstrCryptoCtxt.pu8Rsa,M2M_MAX_RSA_LEN, 0) == M2M_SUCCESS) + { + if (gstrCryptoCtxt.pfAppCryptoCb) + gstrCryptoCtxt.pfAppCryptoCb(u8OpCode,&strResp,gstrCryptoCtxt.pu8Rsa); + } + } + } + else if(u8OpCode == M2M_CRYPTO_RESP_RSA_SIGN_VERIFY) + { + tstrCyptoResp strResp; + if (hif_receive(u32Addr + sizeof(tstrRsaPayload), (uint8*)&strResp,sizeof(tstrCyptoResp), 1) == M2M_SUCCESS) + { + if (gstrCryptoCtxt.pfAppCryptoCb) + gstrCryptoCtxt.pfAppCryptoCb(u8OpCode,&strResp,NULL); + } + } + else + { + M2M_ERR("u8Code %d ??\n",u8OpCode); + } + +} +/*! +@fn \ + sint8 m2m_crypto_init(); + +@brief crypto initialization + +@param[in] pfAppCryproCb + +*/ +sint8 m2m_crypto_init(tpfAppCryproCb pfAppCryproCb) +{ + sint8 ret = M2M_ERR_FAIL; + m2m_memset((uint8*)&gstrCryptoCtxt,0,sizeof(tstrCryptoCtxt)); + if(pfAppCryproCb != NULL) + { + gstrCryptoCtxt.pfAppCryptoCb = pfAppCryproCb; + ret = hif_register_cb(M2M_REQ_GROUP_CRYPTO,m2m_crypto_cb); + } + return ret; +} +/*! +@fn \ + sint8 m2m_sha256_hash_init(tstrM2mSha256Ctxt *psha256Ctxt); + +@brief SHA256 hash initialization + +@param[in] psha256Ctxt + Pointer to a sha256 context allocated by the caller. +*/ +sint8 m2m_crypto_sha256_hash_init(tstrM2mSha256Ctxt *psha256Ctxt) +{ + sint8 ret = M2M_ERR_FAIL; + if((psha256Ctxt != NULL)&&(!gstrCryptoCtxt.u8CryptoBusy)) + { + ret = hif_send(M2M_REQ_GROUP_CRYPTO,M2M_CRYPTO_REQ_SHA256_INIT|M2M_REQ_DATA_PKT,(uint8*)psha256Ctxt,sizeof(tstrM2mSha256Ctxt),NULL,0,0); + } + return ret; +} + + +/*! +@fn \ + sint8 m2m_sha256_hash_update(tstrM2mSha256Ctxt *psha256Ctxt, uint8 *pu8Data, uint16 u16DataLength); + +@brief SHA256 hash update + +@param [in] psha256Ctxt + Pointer to the sha256 context. + +@param [in] pu8Data + Buffer holding the data submitted to the hash. + +@param [in] u16DataLength + Size of the data bufefr in bytes. +*/ +sint8 m2m_crypto_sha256_hash_update(tstrM2mSha256Ctxt *psha256Ctxt, uint8 *pu8Data, uint16 u16DataLength) +{ + sint8 ret = M2M_ERR_FAIL; + if((!gstrCryptoCtxt.u8CryptoBusy) && (psha256Ctxt != NULL) && (pu8Data != NULL) && (u16DataLength < M2M_SHA256_MAX_DATA)) + { + ret = hif_send(M2M_REQ_GROUP_CRYPTO,M2M_CRYPTO_REQ_SHA256_UPDATE|M2M_REQ_DATA_PKT,(uint8*)psha256Ctxt,sizeof(tstrM2mSha256Ctxt),pu8Data,u16DataLength,sizeof(tstrM2mSha256Ctxt) + sizeof(tstrCyptoResp)); + } + return ret; + +} + + +/*! +@fn \ + sint8 m2m_sha256_hash_finish(tstrM2mSha256Ctxt *psha256Ctxt, uint8 *pu8Sha256Digest); + +@brief SHA256 hash finalization + +@param[in] psha256Ctxt + Pointer to a sha256 context allocated by the caller. + +@param [in] pu8Sha256Digest + Buffer allocated by the caller which will hold the resultant SHA256 Digest. It must be allocated no less than M2M_SHA256_DIGEST_LEN. +*/ +sint8 m2m_crypto_sha256_hash_finish(tstrM2mSha256Ctxt *psha256Ctxt, uint8 *pu8Sha256Digest) +{ + sint8 ret = M2M_ERR_FAIL; + if((!gstrCryptoCtxt.u8CryptoBusy) && (psha256Ctxt != NULL) && (pu8Sha256Digest != NULL)) + { + gstrCryptoCtxt.pu8Digest = pu8Sha256Digest; + ret = hif_send(M2M_REQ_GROUP_CRYPTO,M2M_CRYPTO_REQ_SHA256_FINSIH|M2M_REQ_DATA_PKT,(uint8*)psha256Ctxt,sizeof(tstrM2mSha256Ctxt),NULL,0,0); + } + return ret; +} + + + + +/*! +@fn \ + sint8 m2m_rsa_sign_verify(uint8 *pu8N, uint16 u16NSize, uint8 *pu8E, uint16 u16ESize, uint8 *pu8SignedMsgHash, \ + uint16 u16HashLength, uint8 *pu8RsaSignature); + +@brief RSA Signature Verification + + The function shall request the RSA Signature verification from the WINC Firmware for the given message. The signed message shall be + compressed to the corresponding hash algorithm before calling this function. + The hash type is identified by the given hash length. For example, if the hash length is 32 bytes, then it is SHA256. + +@param[in] pu8N + RSA Key modulus n. + +@param[in] u16NSize + Size of the RSA modulus n in bytes. + +@param[in] pu8E + RSA public exponent. + +@param[in] u16ESize + Size of the RSA public exponent in bytes. + +@param[in] pu8SignedMsgHash + The hash digest of the signed message. + +@param[in] u16HashLength + The length of the hash digest. + +@param[out] pu8RsaSignature + Signature value to be verified. +*/ + + +sint8 m2m_crypto_rsa_sign_verify(uint8 *pu8N, uint16 u16NSize, uint8 *pu8E, uint16 u16ESize, uint8 *pu8SignedMsgHash, + uint16 u16HashLength, uint8 *pu8RsaSignature) +{ + sint8 ret = M2M_ERR_FAIL; + if((!gstrCryptoCtxt.u8CryptoBusy) && (pu8N != NULL) && (pu8E != NULL) && (pu8RsaSignature != NULL) && (pu8SignedMsgHash != NULL) + && (u16NSize != 0) && (u16ESize != 0) && (u16HashLength != 0) && (pu8RsaSignature != NULL) ) + + { + tstrRsaPayload strRsa = {0}; + + m2m_memcpy(strRsa.au8N,pu8N,u16NSize); + m2m_memcpy(strRsa.au8E,pu8E,u16ESize); + m2m_memcpy(strRsa.au8Hash,pu8SignedMsgHash,u16HashLength); + + strRsa.u16Esz = u16ESize; + strRsa.u16Hsz = u16HashLength; + strRsa.u16Nsz = u16NSize; + + ret = hif_send(M2M_REQ_GROUP_CRYPTO,M2M_CRYPTO_REQ_RSA_SIGN_VERIFY|M2M_REQ_DATA_PKT,(uint8*)&strRsa,sizeof(tstrRsaPayload),NULL,0,0); + + } + return ret; +} + + +/*! +@fn \ + sint8 m2m_rsa_sign_gen(uint8 *pu8N, uint16 u16NSize, uint8 *pu8d, uint16 u16dSize, uint8 *pu8SignedMsgHash, \ + uint16 u16HashLength, uint8 *pu8RsaSignature); + +@brief RSA Signature Generation + + The function shall request the RSA Signature generation from the WINC Firmware for the given message. The signed message shall be + compressed to the corresponding hash algorithm before calling this function. + The hash type is identified by the given hash length. For example, if the hash length is 32 bytes, then it is SHA256. + +@param[in] pu8N + RSA Key modulus n. + +@param[in] u16NSize + Size of the RSA modulus n in bytes. + +@param[in] pu8d + RSA private exponent. + +@param[in] u16dSize + Size of the RSA private exponent in bytes. + +@param[in] pu8SignedMsgHash + The hash digest of the signed message. + +@param[in] u16HashLength + The length of the hash digest. + +@param[out] pu8RsaSignature + Pointer to a user buffer allocated by teh caller shall hold the generated signature. +*/ +sint8 m2m_crypto_rsa_sign_gen(uint8 *pu8N, uint16 u16NSize, uint8 *pu8d, uint16 u16dSize, uint8 *pu8SignedMsgHash, + uint16 u16HashLength, uint8 *pu8RsaSignature) +{ + sint8 ret = M2M_ERR_FAIL; + if((!gstrCryptoCtxt.u8CryptoBusy) && (pu8N != NULL) && (pu8d != NULL) && (pu8RsaSignature != NULL) && (pu8SignedMsgHash != NULL) + && (u16NSize != 0) && (u16dSize != 0) && (u16HashLength != 0) && (pu8RsaSignature != NULL)) + + { + tstrRsaPayload strRsa = {0}; + + m2m_memcpy(strRsa.au8N,pu8N,u16NSize); + m2m_memcpy(strRsa.au8E,pu8d,u16dSize); + m2m_memcpy(strRsa.au8Hash,pu8SignedMsgHash,u16HashLength); + + strRsa.u16Esz = u16dSize; + strRsa.u16Hsz = u16HashLength; + strRsa.u16Nsz = u16NSize; + + gstrCryptoCtxt.pu8Rsa = pu8RsaSignature; + ret = hif_send(M2M_REQ_GROUP_CRYPTO,M2M_CRYPTO_REQ_RSA_SIGN_GEN|M2M_REQ_DATA_PKT,(uint8*)&strRsa,sizeof(tstrRsaPayload),NULL,0,0); + + } + return ret; +} + +#endif \ No newline at end of file diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/m2m_hif.c b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/m2m_hif.c new file mode 100644 index 0000000000000..f907964d97554 --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/m2m_hif.c @@ -0,0 +1,696 @@ +/** + * + * \file + * + * \brief This module contains M2M host interface APIs implementation. + * + * Copyright (c) 2016-2017 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + +#include "common/include/nm_common.h" +#include "driver/source/nmbus.h" +#include "bsp/include/nm_bsp.h" +#include "m2m_hif.h" +#include "driver/include/m2m_types.h" +#include "driver/source/nmasic.h" +#include "driver/include/m2m_periph.h" + +#if (defined NM_EDGE_INTERRUPT)&&(defined NM_LEVEL_INTERRUPT) +#error "only one type of interrupt NM_EDGE_INTERRUPT,NM_LEVEL_INTERRUPT" +#endif + +#if !((defined NM_EDGE_INTERRUPT)||(defined NM_LEVEL_INTERRUPT)) +#error "define interrupt type NM_EDGE_INTERRUPT,NM_LEVEL_INTERRUPT" +#endif + +#ifndef CORTUS_APP +#define NMI_AHB_DATA_MEM_BASE 0x30000 +#define NMI_AHB_SHARE_MEM_BASE 0xd0000 + +#define WIFI_HOST_RCV_CTRL_0 (0x1070) +#define WIFI_HOST_RCV_CTRL_1 (0x1084) +#define WIFI_HOST_RCV_CTRL_2 (0x1078) +#define WIFI_HOST_RCV_CTRL_3 (0x106c) +#define WIFI_HOST_RCV_CTRL_4 (0x150400) +#define WIFI_HOST_RCV_CTRL_5 (0x1088) + +typedef struct { + uint8 u8ChipMode; + uint8 u8ChipSleep; + uint8 u8HifRXDone; + uint8 u8Interrupt; + uint32 u32RxAddr; + uint32 u32RxSize; + tpfHifCallBack pfWifiCb; + tpfHifCallBack pfIpCb; + tpfHifCallBack pfOtaCb; + tpfHifCallBack pfSigmaCb; + tpfHifCallBack pfHifCb; + tpfHifCallBack pfCryptoCb; + tpfHifCallBack pfSslCb; +}tstrHifContext; + +volatile tstrHifContext gstrHifCxt; + +static void isr(void) +{ + gstrHifCxt.u8Interrupt++; +#ifdef NM_LEVEL_INTERRUPT + nm_bsp_interrupt_ctrl(0); +#endif +} +static sint8 hif_set_rx_done(void) +{ + uint32 reg; + sint8 ret = M2M_SUCCESS; + + gstrHifCxt.u8HifRXDone = 0; +#ifdef NM_EDGE_INTERRUPT + nm_bsp_interrupt_ctrl(1); +#endif + ret = nm_read_reg_with_ret(WIFI_HOST_RCV_CTRL_0,®); + if(ret != M2M_SUCCESS)goto ERR1; + /* Set RX Done */ + reg |= NBIT1; + ret = nm_write_reg(WIFI_HOST_RCV_CTRL_0,reg); + if(ret != M2M_SUCCESS)goto ERR1; +#ifdef NM_LEVEL_INTERRUPT + nm_bsp_interrupt_ctrl(1); +#endif +ERR1: + return ret; + +} +/** +* @fn static void m2m_hif_cb(uint8 u8OpCode, uint16 u16DataSize, uint32 u32Addr) +* @brief WiFi call back function +* @param [in] u8OpCode +* HIF Opcode type. +* @param [in] u16DataSize +* HIF data length. +* @param [in] u32Addr +* HIF address. +* @param [in] grp +* HIF group type. +* @author +* @date +* @version 1.0 +*/ +static void m2m_hif_cb(uint8 u8OpCode, uint16 u16DataSize, uint32 u32Addr) +{ + + +} +/** +* @fn NMI_API sint8 hif_chip_wake(void); +* @brief To Wakeup the chip. +* @return The function shall return ZERO for successful operation and a negative value otherwise. +*/ + +sint8 hif_chip_wake(void) +{ + sint8 ret = M2M_SUCCESS; + if(gstrHifCxt.u8HifRXDone) + { + /*chip already wake for the rx not done no need to send wake request*/ + return ret; + } + if(gstrHifCxt.u8ChipSleep == 0) + { + if(gstrHifCxt.u8ChipMode != M2M_NO_PS) + { + ret = chip_wake(); + if(ret != M2M_SUCCESS)goto ERR1; + } + else + { + } + } + gstrHifCxt.u8ChipSleep++; +ERR1: + return ret; +} +/*! +@fn \ + NMI_API void hif_set_sleep_mode(uint8 u8Pstype); + +@brief + Set the sleep mode of the HIF layer. + +@param [in] u8Pstype + Sleep mode. + +@return + The function SHALL return 0 for success and a negative value otherwise. +*/ + +void hif_set_sleep_mode(uint8 u8Pstype) +{ + gstrHifCxt.u8ChipMode = u8Pstype; +} +/*! +@fn \ + NMI_API uint8 hif_get_sleep_mode(void); + +@brief + Get the sleep mode of the HIF layer. + +@return + The function SHALL return the sleep mode of the HIF layer. +*/ + +uint8 hif_get_sleep_mode(void) +{ + return gstrHifCxt.u8ChipMode; +} + +/** +* @fn NMI_API sint8 hif_chip_sleep_sc(void); +* @brief To clear the chip sleep but keep the chip sleep +* @return The function shall return ZERO for successful operation and a negative value otherwise. +*/ + +sint8 hif_chip_sleep_sc(void) +{ + if(gstrHifCxt.u8ChipSleep >= 1) + { + gstrHifCxt.u8ChipSleep--; + } + return M2M_SUCCESS; +} +/** +* @fn NMI_API sint8 hif_chip_sleep(void); +* @brief To make the chip sleep. +* @return The function shall return ZERO for successful operation and a negative value otherwise. +*/ + +sint8 hif_chip_sleep(void) +{ + sint8 ret = M2M_SUCCESS; + + if(gstrHifCxt.u8ChipSleep >= 1) + { + gstrHifCxt.u8ChipSleep--; + } + + if(gstrHifCxt.u8ChipSleep == 0) + { + if(gstrHifCxt.u8ChipMode != M2M_NO_PS) + { + ret = chip_sleep(); + if(ret != M2M_SUCCESS)goto ERR1; + + } + else + { + } + } +ERR1: + return ret; +} +/** +* @fn NMI_API sint8 hif_init(void * arg); +* @brief To initialize HIF layer. +* @param [in] arg +* Pointer to the arguments. +* @return The function shall return ZERO for successful operation and a negative value otherwise. +*/ + +sint8 hif_init(void * arg) +{ + m2m_memset((uint8*)&gstrHifCxt,0,sizeof(tstrHifContext)); + nm_bsp_register_isr(isr); + hif_register_cb(M2M_REQ_GROUP_HIF,m2m_hif_cb); + return M2M_SUCCESS; +} +/** +* @fn NMI_API sint8 hif_deinit(void * arg); +* @brief To De-initialize HIF layer. +* @param [in] arg +* Pointer to the arguments. +* @return The function shall return ZERO for successful operation and a negative value otherwise. +*/ +sint8 hif_deinit(void * arg) +{ + sint8 ret = M2M_SUCCESS; + ret = hif_chip_wake(); + m2m_memset((uint8*)&gstrHifCxt,0,sizeof(tstrHifContext)); + return ret; +} +/** +* @fn NMI_API sint8 hif_send(uint8 u8Gid,uint8 u8Opcode,uint8 *pu8CtrlBuf,uint16 u16CtrlBufSize, + uint8 *pu8DataBuf,uint16 u16DataSize, uint16 u16DataOffset) +* @brief Send packet using host interface. + +* @param [in] u8Gid +* Group ID. +* @param [in] u8Opcode +* Operation ID. +* @param [in] pu8CtrlBuf +* Pointer to the Control buffer. +* @param [in] u16CtrlBufSize + Control buffer size. +* @param [in] u16DataOffset + Packet Data offset. +* @param [in] pu8DataBuf +* Packet buffer Allocated by the caller. +* @param [in] u16DataSize + Packet buffer size (including the HIF header). +* @return The function shall return ZERO for successful operation and a negative value otherwise. +*/ + +sint8 hif_send(uint8 u8Gid,uint8 u8Opcode,uint8 *pu8CtrlBuf,uint16 u16CtrlBufSize, + uint8 *pu8DataBuf,uint16 u16DataSize, uint16 u16DataOffset) +{ + sint8 ret = M2M_ERR_SEND; + volatile tstrHifHdr strHif; + + strHif.u8Opcode = u8Opcode&(~NBIT7); + strHif.u8Gid = u8Gid; + strHif.u16Length = M2M_HIF_HDR_OFFSET; + if(pu8DataBuf != NULL) + { + strHif.u16Length += u16DataOffset + u16DataSize; + } + else + { + strHif.u16Length += u16CtrlBufSize; + } + ret = hif_chip_wake(); + if(ret == M2M_SUCCESS) + { + volatile uint32 reg, dma_addr = 0; + volatile uint16 cnt = 0; +//#define OPTIMIZE_BUS +/*please define in firmware also*/ +#ifndef OPTIMIZE_BUS + reg = 0UL; + reg |= (uint32)u8Gid; + reg |= ((uint32)u8Opcode<<8); + reg |= ((uint32)strHif.u16Length<<16); + ret = nm_write_reg(NMI_STATE_REG,reg); + if(M2M_SUCCESS != ret) goto ERR1; + + reg = 0UL; + reg |= NBIT1; + ret = nm_write_reg(WIFI_HOST_RCV_CTRL_2, reg); + if(M2M_SUCCESS != ret) goto ERR1; +#else + reg = 0UL; + reg |= NBIT1; + reg |= ((u8Opcode & NBIT7) ? (NBIT2):(0)); /*Data = 1 or config*/ + reg |= (u8Gid == M2M_REQ_GROUP_IP) ? (NBIT3):(0); /*IP = 1 or non IP*/ + reg |= ((uint32)strHif.u16Length << 4); /*length of pkt max = 4096*/ + ret = nm_write_reg(WIFI_HOST_RCV_CTRL_2, reg); + if(M2M_SUCCESS != ret) goto ERR1; +#endif + dma_addr = 0; + + for(cnt = 0; cnt < 1000; cnt ++) + { + ret = nm_read_reg_with_ret(WIFI_HOST_RCV_CTRL_2,(uint32 *)®); + if(ret != M2M_SUCCESS) break; + /* + * If it takes too long to get a response, the slow down to + * avoid back-to-back register read operations. + */ + if(cnt >= 500) { + if(cnt < 501) { + M2M_INFO("Slowing down...\n"); + } + nm_bsp_sleep(1); + } + if (!(reg & NBIT1)) + { + ret = nm_read_reg_with_ret(WIFI_HOST_RCV_CTRL_4,(uint32 *)&dma_addr); + if(ret != M2M_SUCCESS) { + /*in case of read error clear the DMA address and return error*/ + dma_addr = 0; + goto ERR1; + } + /*in case of success break */ + break; + } + } + + if (dma_addr != 0) + { + volatile uint32 u32CurrAddr; + u32CurrAddr = dma_addr; + strHif.u16Length=NM_BSP_B_L_16(strHif.u16Length); + ret = nm_write_block(u32CurrAddr, (uint8*)&strHif, M2M_HIF_HDR_OFFSET); + if(M2M_SUCCESS != ret) goto ERR1; + u32CurrAddr += M2M_HIF_HDR_OFFSET; + if(pu8CtrlBuf != NULL) + { + ret = nm_write_block(u32CurrAddr, pu8CtrlBuf, u16CtrlBufSize); + if(M2M_SUCCESS != ret) goto ERR1; + u32CurrAddr += u16CtrlBufSize; + } + if(pu8DataBuf != NULL) + { + u32CurrAddr += (u16DataOffset - u16CtrlBufSize); + ret = nm_write_block(u32CurrAddr, pu8DataBuf, u16DataSize); + if(M2M_SUCCESS != ret) goto ERR1; + u32CurrAddr += u16DataSize; + } + + reg = dma_addr << 2; + reg |= NBIT1; + ret = nm_write_reg(WIFI_HOST_RCV_CTRL_3, reg); + if(M2M_SUCCESS != ret) goto ERR1; + } + else + { + ret = hif_chip_sleep(); + M2M_DBG("Failed to alloc rx size %d\r",ret); + ret = M2M_ERR_MEM_ALLOC; + goto ERR2; + } + + } + else + { + M2M_ERR("(HIF)Fail to wakup the chip\n"); + goto ERR2; + } + /*actual sleep ret = M2M_SUCCESS*/ + ret = hif_chip_sleep(); + return ret; +ERR1: + /*reset the count but no actual sleep as it already bus error*/ + hif_chip_sleep_sc(); +ERR2: + /*logical error*/ + return ret; +} +/** +* @fn hif_isr +* @brief Host interface interrupt service routine +* @author M. Abdelmawla +* @date 15 July 2012 +* @return 1 in case of interrupt received else 0 will be returned +* @version 1.0 +*/ +static sint8 hif_isr(void) +{ + sint8 ret = M2M_SUCCESS; + uint32 reg; + volatile tstrHifHdr strHif; + + ret = nm_read_reg_with_ret(WIFI_HOST_RCV_CTRL_0, ®); + if(M2M_SUCCESS == ret) + { + if(reg & 0x1) /* New interrupt has been received */ + { + uint16 size; + + nm_bsp_interrupt_ctrl(0); + /*Clearing RX interrupt*/ + reg &= ~NBIT0; + ret = nm_write_reg(WIFI_HOST_RCV_CTRL_0,reg); + if(ret != M2M_SUCCESS)goto ERR1; + gstrHifCxt.u8HifRXDone = 1; + size = (uint16)((reg >> 2) & 0xfff); + if (size > 0) { + uint32 address = 0; + /** + start bus transfer + **/ + ret = nm_read_reg_with_ret(WIFI_HOST_RCV_CTRL_1, &address); + if(M2M_SUCCESS != ret) + { + M2M_ERR("(hif) WIFI_HOST_RCV_CTRL_1 bus fail\n"); + nm_bsp_interrupt_ctrl(1); + goto ERR1; + } + gstrHifCxt.u32RxAddr = address; + gstrHifCxt.u32RxSize = size; + ret = nm_read_block(address, (uint8*)&strHif, sizeof(tstrHifHdr)); + strHif.u16Length = NM_BSP_B_L_16(strHif.u16Length); + if(M2M_SUCCESS != ret) + { + M2M_ERR("(hif) address bus fail\n"); + nm_bsp_interrupt_ctrl(1); + goto ERR1; + } + if(strHif.u16Length != size) + { + if((size - strHif.u16Length) > 4) + { + M2M_ERR("(hif) Corrupted packet Size = %u \n", + size, strHif.u16Length, strHif.u8Gid, strHif.u8Opcode); + nm_bsp_interrupt_ctrl(1); + ret = M2M_ERR_BUS_FAIL; + goto ERR1; + } + } + + if(M2M_REQ_GROUP_WIFI == strHif.u8Gid) + { + if(gstrHifCxt.pfWifiCb) + gstrHifCxt.pfWifiCb(strHif.u8Opcode,strHif.u16Length - M2M_HIF_HDR_OFFSET, address + M2M_HIF_HDR_OFFSET); + else + M2M_ERR("WIFI callback is not registered\n"); + + } + else if(M2M_REQ_GROUP_IP == strHif.u8Gid) + { + if(gstrHifCxt.pfIpCb) + gstrHifCxt.pfIpCb(strHif.u8Opcode,strHif.u16Length - M2M_HIF_HDR_OFFSET, address + M2M_HIF_HDR_OFFSET); + else + M2M_ERR("Scoket callback is not registered\n"); + + } + else if(M2M_REQ_GROUP_OTA == strHif.u8Gid) + { + if(gstrHifCxt.pfOtaCb) + gstrHifCxt.pfOtaCb(strHif.u8Opcode,strHif.u16Length - M2M_HIF_HDR_OFFSET, address + M2M_HIF_HDR_OFFSET); + else + M2M_ERR("Ota callback is not registered\n"); + + } + else if(M2M_REQ_GROUP_CRYPTO == strHif.u8Gid) + { + if(gstrHifCxt.pfCryptoCb) + gstrHifCxt.pfCryptoCb(strHif.u8Opcode,strHif.u16Length - M2M_HIF_HDR_OFFSET, address + M2M_HIF_HDR_OFFSET); + + else + M2M_ERR("Crypto callback is not registered\n"); + } + else if(M2M_REQ_GROUP_SIGMA == strHif.u8Gid) + { + if(gstrHifCxt.pfSigmaCb) + gstrHifCxt.pfSigmaCb(strHif.u8Opcode,strHif.u16Length - M2M_HIF_HDR_OFFSET, address + M2M_HIF_HDR_OFFSET); + else + M2M_ERR("Sigma callback is not registered\n"); + } + else if(M2M_REQ_GROUP_SSL == strHif.u8Gid) + { + if(gstrHifCxt.pfSslCb) + gstrHifCxt.pfSslCb(strHif.u8Opcode,strHif.u16Length - M2M_HIF_HDR_OFFSET, address + M2M_HIF_HDR_OFFSET); + } + else + { + M2M_ERR("(hif) invalid group ID\n"); + ret = M2M_ERR_BUS_FAIL; + goto ERR1; + } + if(gstrHifCxt.u8HifRXDone) + { + M2M_ERR("(hif) host app didn't set RX Done <%u><%X>\n", strHif.u8Gid, strHif.u8Opcode); + ret = hif_set_rx_done(); + if(ret != M2M_SUCCESS) goto ERR1; + } + } + else + { + M2M_ERR("(hif) Wrong Size\n"); + ret = M2M_ERR_RCV; + goto ERR1; + } + } + else + { +#ifndef WIN32 + M2M_ERR("(hif) False interrupt %lx",reg); + ret = M2M_ERR_FAIL; + goto ERR1; +#else +#endif + } + } + else + { + M2M_ERR("(hif) Fail to Read interrupt reg\n"); + goto ERR1; + } + +ERR1: + return ret; +} + +/** +* @fn hif_handle_isr(void) +* @brief Handle interrupt received from NMC1500 firmware. +* @return The function SHALL return 0 for success and a negative value otherwise. +*/ + +sint8 hif_handle_isr(void) +{ + sint8 ret = M2M_SUCCESS; + while (gstrHifCxt.u8Interrupt) { + /*must be at that place because of the race of interrupt increment and that decrement*/ + /*when the interrupt enabled*/ + gstrHifCxt.u8Interrupt--; + while(1) + { + ret = hif_isr(); + if(ret == M2M_SUCCESS) { + /*we will try forever untill we get that interrupt*/ + /*Fail return errors here due to bus errors (reading expected values)*/ + break; + } else { + M2M_ERR("(HIF) Fail to handle interrupt %d try Again..\n",ret); + } + } + } + + return ret; +} +/* +* @fn hif_receive +* @brief Host interface interrupt serviece routine +* @param [in] u32Addr +* Receive start address +* @param [out] pu8Buf +* Pointer to receive buffer. Allocated by the caller +* @param [in] u16Sz +* Receive buffer size +* @param [in] isDone +* If you don't need any more packets send True otherwise send false +* @return The function shall return ZERO for successful operation and a negative value otherwise. +*/ +sint8 hif_receive(uint32 u32Addr, uint8 *pu8Buf, uint16 u16Sz, uint8 isDone) +{ + sint8 ret = M2M_SUCCESS; + if((u32Addr == 0)||(pu8Buf == NULL) || (u16Sz == 0)) + { + if(isDone) + { + /* set RX done */ + ret = hif_set_rx_done(); + } + else + { + ret = M2M_ERR_FAIL; + M2M_ERR(" hif_receive: Invalid argument\n"); + } + goto ERR1; + } + + if(u16Sz > gstrHifCxt.u32RxSize) + { + ret = M2M_ERR_FAIL; + M2M_ERR("APP Requested Size is larger than the recived buffer size <%u><%lu>\n",u16Sz, gstrHifCxt.u32RxSize); + goto ERR1; + } + if((u32Addr < gstrHifCxt.u32RxAddr)||((u32Addr + u16Sz)>(gstrHifCxt.u32RxAddr + gstrHifCxt.u32RxSize))) + { + ret = M2M_ERR_FAIL; + M2M_ERR("APP Requested Address beyond the recived buffer address and length\n"); + goto ERR1; + } + + /* Receive the payload */ + ret = nm_read_block(u32Addr, pu8Buf, u16Sz); + if(ret != M2M_SUCCESS)goto ERR1; + + /* check if this is the last packet */ + if((((gstrHifCxt.u32RxAddr + gstrHifCxt.u32RxSize) - (u32Addr + u16Sz)) <= 0) || isDone) + { + /* set RX done */ + ret = hif_set_rx_done(); + } + +ERR1: + return ret; +} + +/** +* @fn hif_register_cb +* @brief To set Callback function for every compantent Component +* @param [in] u8Grp +* Group to which the Callback function should be set. +* @param [in] fn +* function to be set +* @return The function shall return ZERO for successful operation and a negative value otherwise. +*/ + +sint8 hif_register_cb(uint8 u8Grp,tpfHifCallBack fn) +{ + sint8 ret = M2M_SUCCESS; + switch(u8Grp) + { + case M2M_REQ_GROUP_IP: + gstrHifCxt.pfIpCb = fn; + break; + case M2M_REQ_GROUP_WIFI: + gstrHifCxt.pfWifiCb = fn; + break; + case M2M_REQ_GROUP_OTA: + gstrHifCxt.pfOtaCb = fn; + break; + case M2M_REQ_GROUP_HIF: + gstrHifCxt.pfHifCb = fn; + break; + case M2M_REQ_GROUP_CRYPTO: + gstrHifCxt.pfCryptoCb = fn; + break; + case M2M_REQ_GROUP_SIGMA: + gstrHifCxt.pfSigmaCb = fn; + break; + case M2M_REQ_GROUP_SSL: + gstrHifCxt.pfSslCb = fn; + break; + default: + M2M_ERR("GRp ? %d\n",u8Grp); + ret = M2M_ERR_FAIL; + break; + } + return ret; +} + +#endif diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/m2m_hif.h b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/m2m_hif.h new file mode 100644 index 0000000000000..11871832d8b2f --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/m2m_hif.h @@ -0,0 +1,249 @@ +/** + * + * \file + * + * \brief This module contains M2M host interface APIs implementation. + * + * Copyright (c) 2016-2017 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + +#ifndef _M2M_HIF_ +#define _M2M_HIF_ + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +INCLUDES +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ + +#include "common/include/nm_common.h" +/*!< Include depends on UNO Board is used or not*/ +#ifdef ENABLE_UNO_BOARD +#include "m2m_uno_hif.h" +#endif + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +MACROS +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ + +#define M2M_HIF_MAX_PACKET_SIZE (1600 - 4) +/*!< Maximum size of the buffer could be transferred between Host and Firmware. +*/ + +#define M2M_HIF_HDR_OFFSET (sizeof(tstrHifHdr) + 4) + +/** +* @struct tstrHifHdr +* @brief Structure to hold HIF header +*/ +typedef struct +{ + uint8 u8Gid; /*!< Group ID */ + uint8 u8Opcode; /*!< OP code */ + uint16 u16Length; /*!< Payload length */ +}tstrHifHdr; + +#ifdef __cplusplus + extern "C" { +#endif + +/*! +@typedef typedef void (*tpfHifCallBack)(uint8 u8OpCode, uint16 u16DataSize, uint32 u32Addr); +@brief used to point to Wi-Fi call back function depend on Arduino project or other projects. +@param [in] u8OpCode + HIF Opcode type. +@param [in] u16DataSize + HIF data length. +@param [in] u32Addr + HIF address. +@param [in] grp + HIF group type. +*/ +typedef void (*tpfHifCallBack)(uint8 u8OpCode, uint16 u16DataSize, uint32 u32Addr); +/** +* @fn NMI_API sint8 hif_init(void * arg); +* @brief + To initialize HIF layer. +* @param [in] arg +* Pointer to the arguments. +* @return + The function shall return ZERO for successful operation and a negative value otherwise. +*/ +NMI_API sint8 hif_init(void * arg); +/** +* @fn NMI_API sint8 hif_deinit(void * arg); +* @brief + To Deinitialize HIF layer. +* @param [in] arg +* Pointer to the arguments. +* @return + The function shall return ZERO for successful operation and a negative value otherwise. +*/ +NMI_API sint8 hif_deinit(void * arg); +/** +* @fn NMI_API sint8 hif_send(uint8 u8Gid,uint8 u8Opcode,uint8 *pu8CtrlBuf,uint16 u16CtrlBufSize, + uint8 *pu8DataBuf,uint16 u16DataSize, uint16 u16DataOffset) +* @brief Send packet using host interface. + +* @param [in] u8Gid +* Group ID. +* @param [in] u8Opcode +* Operation ID. +* @param [in] pu8CtrlBuf +* Pointer to the Control buffer. +* @param [in] u16CtrlBufSize + Control buffer size. +* @param [in] u16DataOffset + Packet Data offset. +* @param [in] pu8DataBuf +* Packet buffer Allocated by the caller. +* @param [in] u16DataSize + Packet buffer size (including the HIF header). +* @return The function shall return ZERO for successful operation and a negative value otherwise. +*/ +NMI_API sint8 hif_send(uint8 u8Gid,uint8 u8Opcode,uint8 *pu8CtrlBuf,uint16 u16CtrlBufSize, + uint8 *pu8DataBuf,uint16 u16DataSize, uint16 u16DataOffset); +/* +* @fn hif_receive +* @brief Host interface interrupt serviece routine +* @param [in] u32Addr +* Receive start address +* @param [out] pu8Buf +* Pointer to receive buffer. Allocated by the caller +* @param [in] u16Sz +* Receive buffer size +* @param [in] isDone +* If you don't need any more packets send True otherwise send false +* @return + The function shall return ZERO for successful operation and a negative value otherwise. +*/ + +NMI_API sint8 hif_receive(uint32 u32Addr, uint8 *pu8Buf, uint16 u16Sz, uint8 isDone); +/** +* @fn hif_register_cb +* @brief + To set Callback function for every Component. + +* @param [in] u8Grp +* Group to which the Callback function should be set. + +* @param [in] fn +* function to be set to the specified group. +* @return + The function shall return ZERO for successful operation and a negative value otherwise. +*/ +NMI_API sint8 hif_register_cb(uint8 u8Grp,tpfHifCallBack fn); +/** +* @fn NMI_API sint8 hif_chip_sleep(void); +* @brief + To make the chip sleep. +* @return + The function shall return ZERO for successful operation and a negative value otherwise. +*/ +NMI_API sint8 hif_chip_sleep(void); +/** +* @fn NMI_API sint8 hif_chip_sleep_sc(void); +* @brief + To clear the chip count only but keep the chip awake +* @return + The function shall return ZERO for successful operation and a negative value otherwise. +*/ +NMI_API sint8 hif_chip_sleep_sc(void); +/** +* @fn NMI_API sint8 hif_chip_wake(void); +* @brief + To Wakeup the chip. +* @return + The function shall return ZERO for successful operation and a negative value otherwise. +*/ + +NMI_API sint8 hif_chip_wake(void); +/*! +@fn \ + NMI_API void hif_set_sleep_mode(uint8 u8Pstype); + +@brief + Set the sleep mode of the HIF layer. + +@param [in] u8Pstype + Sleep mode. + +@return + The function SHALL return 0 for success and a negative value otherwise. +*/ + +NMI_API void hif_set_sleep_mode(uint8 u8Pstype); +/*! +@fn \ + NMI_API uint8 hif_get_sleep_mode(void); + +@brief + Get the sleep mode of the HIF layer. + +@return + The function SHALL return the sleep mode of the HIF layer. +*/ + +NMI_API uint8 hif_get_sleep_mode(void); + +#ifdef CORTUS_APP +/** +* @fn hif_Resp_handler(uint8 *pu8Buffer, uint16 u16BufferSize) +* @brief + Response handler for HIF layer. + +* @param [in] pu8Buffer + Pointer to the buffer. + +* @param [in] u16BufferSize + Buffer size. + +* @return + The function SHALL return 0 for success and a negative value otherwise. +*/ +NMI_API sint8 hif_Resp_handler(uint8 *pu8Buffer, uint16 u16BufferSize); +#endif + +/** +* @fn hif_handle_isr(void) +* @brief + Handle interrupt received from NMC1500 firmware. +* @return + The function SHALL return 0 for success and a negative value otherwise. +*/ +NMI_API sint8 hif_handle_isr(void); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/m2m_ota.c b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/m2m_ota.c new file mode 100644 index 0000000000000..c55e8126314e2 --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/m2m_ota.c @@ -0,0 +1,411 @@ +/** + * + * \file + * + * \brief NMC1500 IoT OTA Interface. + * + * Copyright (c) 2016-2017 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + + + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +INCLUDES +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ +#include "common/include/nm_common.h" +#include "driver/include/m2m_types.h" +#include "driver/include/m2m_ota.h" +#include "driver/source/m2m_hif.h" +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +MACROS +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +DATA TYPES +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ +static tpfOtaUpdateCb gpfOtaUpdateCb = NULL; +static tpfOtaNotifCb gpfOtaNotifCb = NULL; + + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +FUNCTION PROTOTYPES +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ +/** +* @fn m2m_wifi_cb(uint8 u8OpCode, uint16 u16DataSize, uint32 u32Addr, uint8 grp) +* @brief WiFi call back function +* @param [in] u8OpCode +* HIF Opcode type. +* @param [in] u16DataSize +* HIF data length. +* @param [in] u32Addr +* HIF address. +* @param [in] grp +* HIF group type. +* @author +* @date +* @version 1.0 +*/ +static void m2m_ota_cb(uint8 u8OpCode, uint16 u16DataSize, uint32 u32Addr) +{ + sint8 ret = M2M_SUCCESS; + if(u8OpCode == M2M_OTA_RESP_NOTIF_UPDATE_INFO) + { + tstrOtaUpdateInfo strOtaUpdateInfo; + m2m_memset((uint8*)&strOtaUpdateInfo,0,sizeof(tstrOtaUpdateInfo)); + ret = hif_receive(u32Addr,(uint8*)&strOtaUpdateInfo,sizeof(tstrOtaUpdateInfo),0); + if(ret == M2M_SUCCESS) + { + if(gpfOtaNotifCb) + gpfOtaNotifCb(&strOtaUpdateInfo); + } + } + else if (u8OpCode == M2M_OTA_RESP_UPDATE_STATUS) + { + tstrOtaUpdateStatusResp strOtaUpdateStatusResp; + m2m_memset((uint8*)&strOtaUpdateStatusResp,0,sizeof(tstrOtaUpdateStatusResp)); + ret = hif_receive(u32Addr, (uint8*) &strOtaUpdateStatusResp,sizeof(tstrOtaUpdateStatusResp), 0); + if(ret == M2M_SUCCESS) + { + if(gpfOtaUpdateCb) + gpfOtaUpdateCb(strOtaUpdateStatusResp.u8OtaUpdateStatusType,strOtaUpdateStatusResp.u8OtaUpdateStatus); + } + } + else + { + M2M_ERR("Invaild OTA resp %d ?\n",u8OpCode); + } + +} +/*! +@fn \ + NMI_API sint8 m2m_ota_init(tpfOtaUpdateCb pfOtaUpdateCb, tpfOtaNotifCb pfOtaNotifCb); + +@brief + Initialize the OTA layer. + +@param [in] pfOtaUpdateCb + OTA Update callback function + +@param [in] pfOtaNotifCb + OTA notify callback function + +@return + The function SHALL return 0 for success and a negative value otherwise. +*/ +NMI_API sint8 m2m_ota_init(tpfOtaUpdateCb pfOtaUpdateCb, tpfOtaNotifCb pfOtaNotifCb) +{ + sint8 ret = M2M_SUCCESS; + + if(pfOtaUpdateCb){ + gpfOtaUpdateCb = pfOtaUpdateCb; + }else{ + M2M_ERR("Invaild Ota update cb\n"); + } + if(pfOtaNotifCb){ + gpfOtaNotifCb = pfOtaNotifCb; + }else{ + M2M_ERR("Invaild Ota notify cb\n"); + } + + hif_register_cb(M2M_REQ_GROUP_OTA,m2m_ota_cb); + + return ret; +} +/*! +@fn \ + NMI_API sint8 m2m_ota_notif_set_url(uint8 * u8Url); + +@brief + Set the OTA url + +@param [in] u8Url + The url server address + +@return + The function SHALL return 0 for success and a negative value otherwise. +*/ +NMI_API sint8 m2m_ota_notif_set_url(uint8 * u8Url) +{ + sint8 ret = M2M_SUCCESS; + uint16 u16UrlSize = m2m_strlen(u8Url) + 1; + /*Todo: we may change it to data pkt but we need to give it higer priority + but the priorty is not implemnted yet in data pkt + */ + ret = hif_send(M2M_REQ_GROUP_OTA,M2M_OTA_REQ_NOTIF_SET_URL,u8Url,u16UrlSize,NULL,0,0); + return ret; + +} + +/*! +@fn \ + NMI_API sint8 m2m_ota_notif_check_for_update(void); + +@brief + check for ota update + +@return + The function SHALL return 0 for success and a negative value otherwise. +*/ +NMI_API sint8 m2m_ota_notif_check_for_update(void) +{ + sint8 ret = M2M_SUCCESS; + ret = hif_send(M2M_REQ_GROUP_OTA,M2M_OTA_REQ_NOTIF_CHECK_FOR_UPDATE,NULL,0,NULL,0,0); + return ret; +} + +/*! +@fn \ + NMI_API sint8 m2m_ota_notif_sched(uint32 u32Period); + +@brief + Schedule OTA update + +@param [in] u32Period + Period in days + +@return + The function SHALL return 0 for success and a negative value otherwise. +*/ +NMI_API sint8 m2m_ota_notif_sched(uint32 u32Period) +{ + sint8 ret = M2M_SUCCESS; + ret = hif_send(M2M_REQ_GROUP_OTA,M2M_OTA_REQ_NOTIF_CHECK_FOR_UPDATE,NULL,0,NULL,0,0); + return ret; +} + +/*! +@fn \ + NMI_API sint8 m2m_ota_start_update(uint8 * u8DownloadUrl); + +@brief + Request OTA start update using the downloaded url + +@param [in] u8DownloadUrl + The download firmware url, you get it from device info + +@return + The function SHALL return 0 for success and a negative value otherwise. + +*/ +NMI_API sint8 m2m_ota_start_update(uint8 * u8DownloadUrl) +{ + sint8 ret = M2M_SUCCESS; + uint16 u16DurlSize = m2m_strlen(u8DownloadUrl) + 1; + /*Todo: we may change it to data pkt but we need to give it higer priority + but the priorty is not implemnted yet in data pkt + */ + ret = hif_send(M2M_REQ_GROUP_OTA,M2M_OTA_REQ_START_FW_UPDATE,u8DownloadUrl,u16DurlSize,NULL,0,0); + return ret; +} +/*! +@fn \ + NMI_API sint8 m2m_ota_start_update_crt(uint8 * u8DownloadUrl); + +@brief + Request OTA start for the Cortus app image. + +@param [in] u8DownloadUrl + The cortus application image url. + +@return + The function SHALL return 0 for success and a negative value otherwise. + +*/ +NMI_API sint8 m2m_ota_start_update_crt(uint8 * u8DownloadUrl) +{ + sint8 ret = M2M_SUCCESS; + uint16 u16DurlSize = m2m_strlen(u8DownloadUrl) + 1; + ret = hif_send(M2M_REQ_GROUP_OTA,M2M_OTA_REQ_START_CRT_UPDATE,u8DownloadUrl,u16DurlSize,NULL,0,0); + return ret; +} + + +/*! +@fn \ + NMI_API sint8 m2m_ota_rollback(void); + +@brief + Request OTA Rollback image + +@return + The function SHALL return 0 for success and a negative value otherwise. +*/ +NMI_API sint8 m2m_ota_rollback(void) +{ + sint8 ret = M2M_SUCCESS; + ret = hif_send(M2M_REQ_GROUP_OTA,M2M_OTA_REQ_ROLLBACK_FW,NULL,0,NULL,0,0); + return ret; +} +/*! +@fn \ + NMI_API sint8 m2m_ota_rollback_crt(void); + +@brief + Request Cortus application OTA Rollback image + +@return + The function SHALL return 0 for success and a negative value otherwise. +*/ +NMI_API sint8 m2m_ota_rollback_crt(void) +{ + sint8 ret = M2M_SUCCESS; + ret = hif_send(M2M_REQ_GROUP_OTA,M2M_OTA_REQ_ROLLBACK_CRT,NULL,0,NULL,0,0); + return ret; +} + +/*! +@fn \ + NMI_API sint8 m2m_ota_abort(void); + +@brief + Request OTA Abort + +@return + The function SHALL return 0 for success and a negative value otherwise. +*/ +NMI_API sint8 m2m_ota_abort(void) +{ + sint8 ret = M2M_SUCCESS; + ret = hif_send(M2M_REQ_GROUP_OTA,M2M_OTA_REQ_ABORT,NULL,0,NULL,0,0); + return ret; +} + + +/*! +@fn \ + NMI_API sint8 m2m_ota_switch_firmware(void); + +@brief + Switch to the upgraded Firmware + +@return + The function SHALL return 0 for success and a negative value otherwise. +*/ +NMI_API sint8 m2m_ota_switch_firmware(void) +{ + sint8 ret = M2M_SUCCESS; + ret = hif_send(M2M_REQ_GROUP_OTA,M2M_OTA_REQ_SWITCH_FIRMWARE,NULL,0,NULL,0,0); + return ret; +} +/*! +@fn \ + NMI_API sint8 m2m_ota_switch_crt(void); + +@brief + Switch to the upgraded cortus application. + +@return + The function SHALL return 0 for success and a negative value otherwise. +*/ +NMI_API sint8 m2m_ota_switch_crt(void) +{ + sint8 ret = M2M_SUCCESS; + ret = hif_send(M2M_REQ_GROUP_OTA,M2M_OTA_REQ_SWITCH_CRT_IMG,NULL,0,NULL,0,0); + return ret; +} + +/*! +@fn \ + NMI_API sint8 m2m_ota_get_firmware_version(tstrM2mRev * pstrRev); + +@brief + Get the OTA Firmware version. + +@return + The function SHALL return 0 for success and a negative value otherwise. +*/ +NMI_API sint8 m2m_ota_get_firmware_version(tstrM2mRev * pstrRev) +{ + sint8 ret = M2M_SUCCESS; + ret = hif_chip_wake(); + if(ret == M2M_SUCCESS) + { + ret = nm_get_ota_firmware_info(pstrRev); + hif_chip_sleep(); + } + return ret; +} +#if 0 +#define M2M_OTA_FILE "../../../m2m_ota.dat" +NMI_API sint8 m2m_ota_test(void) +{ + uint32 page = 0; + uint8 buffer[1500]; + uint32 u32Sz = 0; + sint8 ret = M2M_SUCCESS; + FILE *fp =NULL; + fp = fopen(M2M_OTA_FILE,"rb"); + if(fp) + { + fseek(fp, 0L, SEEK_END); + u32Sz = ftell(fp); + fseek(fp, 0L, SEEK_SET); + + while(u32Sz > 0) + { + { + page = (rand()%1400); + + if((page<100)||(page>1400)) page = 1400; + } + + if(u32Sz>page) + { + u32Sz-=page; + } + else + { + page = u32Sz; + u32Sz = 0; + } + printf("page %d\n", (int)page); + fread(buffer,page,1,fp); + ret = hif_send(M2M_REQ_GROUP_OTA,M2M_OTA_REQ_TEST|M2M_REQ_DATA_PKT,NULL,0,(uint8*)&buffer,page,0); + if(ret != M2M_SUCCESS) + { + M2M_ERR("\n"); + } + nm_bsp_sleep(1); + } + + } + else + { + M2M_ERR("nO err\n"); + } + return ret; +} +#endif + diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/m2m_periph.c b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/m2m_periph.c new file mode 100644 index 0000000000000..ce51f691f146e --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/m2m_periph.c @@ -0,0 +1,161 @@ +/** + * + * \file + * + * \brief NMC1500 Peripherials Application Interface. + * + * Copyright (c) 2016-2017 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +INCLUDES +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ + +#include "driver/include/m2m_periph.h" +#include "driver/source/nmasic.h" +#include "m2m_hif.h" + +#ifdef CONF_PERIPH + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +MACROS +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ +#define GPIO_OP_DIR 0 +#define GPIO_OP_SET 1 +#define GPIO_OP_GET 2 +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +DATA TYPES +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +STATIC FUNCTIONS +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ +static sint8 get_gpio_idx(uint8 u8GpioNum) +{ + if(u8GpioNum >= M2M_PERIPH_GPIO_MAX) return -1; + if(u8GpioNum == M2M_PERIPH_GPIO15) { return 15; + } else if(u8GpioNum == M2M_PERIPH_GPIO16) { return 16; + } else if(u8GpioNum == M2M_PERIPH_GPIO18) { return 18; + } else if(u8GpioNum == M2M_PERIPH_GPIO3) { return 3; + } else if(u8GpioNum == M2M_PERIPH_GPIO4) { return 4; + } else if(u8GpioNum == M2M_PERIPH_GPIO5) { return 5; + } else if(u8GpioNum == M2M_PERIPH_GPIO6) { return 6; + } else { + return -2; + } +} +/* + * GPIO read/write skeleton with wakeup/sleep capability. + */ +static sint8 gpio_ioctl(uint8 op, uint8 u8GpioNum, uint8 u8InVal, uint8 * pu8OutVal) +{ + sint8 ret, gpio; + + ret = hif_chip_wake(); + if(ret != M2M_SUCCESS) goto _EXIT; + + gpio = get_gpio_idx(u8GpioNum); + if(gpio < 0) goto _EXIT1; + + if(op == GPIO_OP_DIR) { + ret = set_gpio_dir((uint8)gpio, u8InVal); + } else if(op == GPIO_OP_SET) { + ret = set_gpio_val((uint8)gpio, u8InVal); + } else if(op == GPIO_OP_GET) { + ret = get_gpio_val((uint8)gpio, pu8OutVal); + } + if(ret != M2M_SUCCESS) goto _EXIT1; + +_EXIT1: + ret = hif_chip_sleep(); +_EXIT: + return ret; +} +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +FUNCTION IMPLEMENTATION +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ + + +sint8 m2m_periph_init(tstrPerphInitParam * param) +{ + return M2M_SUCCESS; +} + +sint8 m2m_periph_gpio_set_dir(uint8 u8GpioNum, uint8 u8GpioDir) +{ + return gpio_ioctl(GPIO_OP_DIR, u8GpioNum, u8GpioDir, NULL); +} + +sint8 m2m_periph_gpio_set_val(uint8 u8GpioNum, uint8 u8GpioVal) +{ + return gpio_ioctl(GPIO_OP_SET, u8GpioNum, u8GpioVal, NULL); +} + +sint8 m2m_periph_gpio_get_val(uint8 u8GpioNum, uint8 * pu8GpioVal) +{ + return gpio_ioctl(GPIO_OP_GET, u8GpioNum, 0, pu8GpioVal); +} + +sint8 m2m_periph_gpio_pullup_ctrl(uint8 u8GpioNum, uint8 u8PullupEn) +{ + /* TBD */ + return M2M_SUCCESS; +} + +sint8 m2m_periph_i2c_master_init(tstrI2cMasterInitParam * param) +{ + /* TBD */ + return M2M_SUCCESS; +} + +sint8 m2m_periph_i2c_master_write(uint8 u8SlaveAddr, uint8 * pu8Buf, uint16 u16BufLen, uint8 flags) +{ + /* TBD */ + return M2M_SUCCESS; +} + +sint8 m2m_periph_i2c_master_read(uint8 u8SlaveAddr, uint8 * pu8Buf, uint16 u16BufLen, uint16 * pu16ReadLen, uint8 flags) +{ + /* TBD */ + return M2M_SUCCESS; +} + + +sint8 m2m_periph_pullup_ctrl(uint32 pinmask, uint8 enable) +{ + return pullup_ctrl(pinmask, enable); +} +#endif /* CONF_PERIPH */ \ No newline at end of file diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/m2m_wifi.c b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/m2m_wifi.c new file mode 100644 index 0000000000000..5d4d865ced30c --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/m2m_wifi.c @@ -0,0 +1,1426 @@ +/** + * + * \file + * + * \brief This module contains M2M Wi-Fi APIs implementation. + * + * Copyright (c) 2016-2017 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + +#include "driver/include/m2m_wifi.h" +#include "driver/source/m2m_hif.h" +#include "driver/source/nmasic.h" + +/** + * \defgroup winc1500_group WINC1500 (Wi-Fi) + * + * \{ + */ + +static volatile uint8 gu8ChNum; +static volatile uint8 gu8scanInProgress = 0; +static tpfAppWifiCb gpfAppWifiCb = NULL; + + +#ifdef ETH_MODE +static tpfAppEthCb gpfAppEthCb = NULL; +static uint8* gau8ethRcvBuf=NULL; +static uint16 gu16ethRcvBufSize ; +#endif + + +//#define CONF_MGMT +#ifdef CONF_MGMT +static tpfAppMonCb gpfAppMonCb = NULL; +static struct _tstrMgmtCtrl +{ + uint8* pu8Buf; + uint16 u16Offset; + uint16 u16Sz; +} +gstrMgmtCtrl = {NULL, 0 , 0}; +#endif +/** +* @fn m2m_wifi_cb(uint8 u8OpCode, uint16 u16DataSize, uint32 u32Addr, uint8 grp) +* @brief WiFi call back function +* @param [in] u8OpCode +* HIF Opcode type. +* @param [in] u16DataSize +* HIF data length. +* @param [in] u32Addr +* HIF address. +* @param [in] grp +* HIF group type. +* @author +* @date +* @version 1.0 +*/ +static void m2m_wifi_cb(uint8 u8OpCode, uint16 u16DataSize, uint32 u32Addr) +{ + uint8 rx_buf[8]; + if (u8OpCode == M2M_WIFI_RESP_CON_STATE_CHANGED) + { + tstrM2mWifiStateChanged strState; + if (hif_receive(u32Addr, (uint8*) &strState,sizeof(tstrM2mWifiStateChanged), 0) == M2M_SUCCESS) + { + if (gpfAppWifiCb) + gpfAppWifiCb(M2M_WIFI_RESP_CON_STATE_CHANGED, &strState); + } + } + else if (u8OpCode == M2M_WIFI_RESP_GET_SYS_TIME) + { + tstrSystemTime strSysTime; + if (hif_receive(u32Addr, (uint8*) &strSysTime,sizeof(tstrSystemTime), 0) == M2M_SUCCESS) + { + if (gpfAppWifiCb) + gpfAppWifiCb(M2M_WIFI_RESP_GET_SYS_TIME, &strSysTime); + } + } + else if(u8OpCode == M2M_WIFI_RESP_CONN_INFO) + { + tstrM2MConnInfo strConnInfo; + if(hif_receive(u32Addr, (uint8*)&strConnInfo, sizeof(tstrM2MConnInfo), 1) == M2M_SUCCESS) + { + if(gpfAppWifiCb) + gpfAppWifiCb(M2M_WIFI_RESP_CONN_INFO, &strConnInfo); + } + } + else if (u8OpCode == M2M_WIFI_RESP_MEMORY_RECOVER) + { +#if 0 + if (hif_receive(u32Addr, rx_buf, 4, 1) == M2M_SUCCESS) + { + tstrM2mWifiStateChanged strState; + m2m_memcpy((uint8*) &strState, rx_buf,sizeof(tstrM2mWifiStateChanged)); + if (app_wifi_recover_cb) + app_wifi_recover_cb(strState.u8CurrState); + } +#endif + } + else if (u8OpCode == M2M_WIFI_REQ_DHCP_CONF) + { + tstrM2MIPConfig strIpConfig; + if (hif_receive(u32Addr, (uint8 *)&strIpConfig, sizeof(tstrM2MIPConfig), 0) == M2M_SUCCESS) + { + if (gpfAppWifiCb) + gpfAppWifiCb(M2M_WIFI_REQ_DHCP_CONF, (uint8 *)&strIpConfig); + } + } + else if (u8OpCode == M2M_WIFI_REQ_WPS) + { + tstrM2MWPSInfo strWps; + m2m_memset((uint8*)&strWps,0,sizeof(tstrM2MWPSInfo)); + if(hif_receive(u32Addr, (uint8*)&strWps, sizeof(tstrM2MWPSInfo), 0) == M2M_SUCCESS) + { + if (gpfAppWifiCb) + gpfAppWifiCb(M2M_WIFI_REQ_WPS, &strWps); + } + } + else if (u8OpCode == M2M_WIFI_RESP_IP_CONFLICT) + { + uint32 u32ConflictedIP; + if(hif_receive(u32Addr, (uint8 *)&u32ConflictedIP, sizeof(u32ConflictedIP), 0) == M2M_SUCCESS) + { + M2M_INFO("Conflicted IP \" %u.%u.%u.%u \" \n", + BYTE_0(u32ConflictedIP),BYTE_1(u32ConflictedIP),BYTE_2(u32ConflictedIP),BYTE_3(u32ConflictedIP)); + if (gpfAppWifiCb) + gpfAppWifiCb(M2M_WIFI_RESP_IP_CONFLICT, NULL); + + } + } + else if (u8OpCode == M2M_WIFI_RESP_SCAN_DONE) + { + tstrM2mScanDone strState; + gu8scanInProgress = 0; + if(hif_receive(u32Addr, (uint8*)&strState, sizeof(tstrM2mScanDone), 0) == M2M_SUCCESS) + { + gu8ChNum = strState.u8NumofCh; + if (gpfAppWifiCb) + gpfAppWifiCb(M2M_WIFI_RESP_SCAN_DONE, &strState); + } + } + else if (u8OpCode == M2M_WIFI_RESP_SCAN_RESULT) + { + tstrM2mWifiscanResult strScanResult; + if(hif_receive(u32Addr, (uint8*)&strScanResult, sizeof(tstrM2mWifiscanResult), 0) == M2M_SUCCESS) + { + if (gpfAppWifiCb) + gpfAppWifiCb(M2M_WIFI_RESP_SCAN_RESULT, &strScanResult); + } + } + else if (u8OpCode == M2M_WIFI_RESP_CURRENT_RSSI) + { + if (hif_receive(u32Addr, rx_buf, 4, 0) == M2M_SUCCESS) + { + if (gpfAppWifiCb) + gpfAppWifiCb(M2M_WIFI_RESP_CURRENT_RSSI, rx_buf); + } + } + else if (u8OpCode == M2M_WIFI_RESP_CLIENT_INFO) + { + if (hif_receive(u32Addr, rx_buf, 4, 0) == M2M_SUCCESS) + { + if (gpfAppWifiCb) + gpfAppWifiCb(M2M_WIFI_RESP_CLIENT_INFO, rx_buf); + } + } + else if(u8OpCode == M2M_WIFI_RESP_PROVISION_INFO) + { + tstrM2MProvisionInfo strProvInfo; + if(hif_receive(u32Addr, (uint8*)&strProvInfo, sizeof(tstrM2MProvisionInfo), 1) == M2M_SUCCESS) + { + if(gpfAppWifiCb) + gpfAppWifiCb(M2M_WIFI_RESP_PROVISION_INFO, &strProvInfo); + } + } + else if(u8OpCode == M2M_WIFI_RESP_DEFAULT_CONNECT) + { + tstrM2MDefaultConnResp strResp; + if(hif_receive(u32Addr, (uint8*)&strResp, sizeof(tstrM2MDefaultConnResp), 1) == M2M_SUCCESS) + { + if(gpfAppWifiCb) + gpfAppWifiCb(M2M_WIFI_RESP_DEFAULT_CONNECT, &strResp); + } + } + + else if(u8OpCode == M2M_WIFI_RESP_GET_PRNG) + { + tstrPrng strPrng; + if(hif_receive(u32Addr, (uint8*)&strPrng,sizeof(tstrPrng), 0) == M2M_SUCCESS) + { + if(hif_receive(u32Addr + sizeof(tstrPrng),strPrng.pu8RngBuff,strPrng.u16PrngSize, 1) == M2M_SUCCESS) + { + if(gpfAppWifiCb) + gpfAppWifiCb(M2M_WIFI_RESP_GET_PRNG,&strPrng); + } + } + } +#ifdef ETH_MODE + else if(u8OpCode == M2M_WIFI_RESP_ETHERNET_RX_PACKET) + { + uint8 u8SetRxDone; + tstrM2mIpRsvdPkt strM2mRsvd; + if(hif_receive(u32Addr, &strM2mRsvd ,sizeof(tstrM2mIpRsvdPkt), 0) == M2M_SUCCESS) + { + tstrM2mIpCtrlBuf strM2mIpCtrlBuf; + uint16 u16Offset = strM2mRsvd.u16PktOffset; + strM2mIpCtrlBuf.u16RemainigDataSize = strM2mRsvd.u16PktSz; + if((gpfAppEthCb) && (gau8ethRcvBuf) && (gu16ethRcvBufSize > 0)) + { + do + { + u8SetRxDone = 1; + if(strM2mIpCtrlBuf.u16RemainigDataSize > gu16ethRcvBufSize) + { + u8SetRxDone = 0; + strM2mIpCtrlBuf.u16DataSize = gu16ethRcvBufSize; + } + else + { + strM2mIpCtrlBuf.u16DataSize = strM2mIpCtrlBuf.u16RemainigDataSize; + } + + if(hif_receive(u32Addr + u16Offset, gau8ethRcvBuf, strM2mIpCtrlBuf.u16DataSize, u8SetRxDone) == M2M_SUCCESS) + { + strM2mIpCtrlBuf.u16RemainigDataSize -= strM2mIpCtrlBuf.u16DataSize; + u16Offset += strM2mIpCtrlBuf.u16DataSize; + gpfAppEthCb(M2M_WIFI_RESP_ETHERNET_RX_PACKET, gau8ethRcvBuf, &(strM2mIpCtrlBuf)); + } + else + { + break; + } + }while (strM2mIpCtrlBuf.u16RemainigDataSize > 0); + } + } + } +#endif /* ETH_MODE */ +#ifdef CONF_MGMT + else if(u8OpCode == M2M_WIFI_RESP_WIFI_RX_PACKET) + { + + tstrM2MWifiRxPacketInfo strRxPacketInfo; + if(u16DataSize >= sizeof(tstrM2MWifiRxPacketInfo)) { + if(hif_receive(u32Addr, (uint8*)&strRxPacketInfo, sizeof(tstrM2MWifiRxPacketInfo), 0) == M2M_SUCCESS) + { + u16DataSize -= sizeof(tstrM2MWifiRxPacketInfo); + if(u16DataSize > 0 && gstrMgmtCtrl.pu8Buf != NULL) + { + if(u16DataSize > (gstrMgmtCtrl.u16Sz + gstrMgmtCtrl.u16Offset)) + { + u16DataSize = gstrMgmtCtrl.u16Sz; + } + u32Addr += sizeof(tstrM2MWifiRxPacketInfo) + gstrMgmtCtrl.u16Offset; + if(hif_receive(u32Addr , gstrMgmtCtrl.pu8Buf, u16DataSize, 1) != M2M_SUCCESS) return; + } + if(gpfAppMonCb) + gpfAppMonCb(&strRxPacketInfo, gstrMgmtCtrl.pu8Buf,u16DataSize); + } + } else { + M2M_ERR("Incorrect mon data size %u\n", u16DataSize); + } + } +#endif + else + { + M2M_ERR("REQ Not defined %d\n",u8OpCode); + } +} + +sint8 m2m_wifi_download_mode() +{ + sint8 ret = M2M_SUCCESS; + /* Apply device specific initialization. */ + ret = nm_drv_init_download_mode(); + if(ret != M2M_SUCCESS) goto _EXIT0; + + + + enable_interrupts(); + +_EXIT0: + return ret; +} + +static sint8 m2m_validate_ap_parameters(CONST tstrM2MAPConfig* pstrM2MAPConfig) +{ + sint8 s8Ret = M2M_SUCCESS; + /* Check for incoming pointer */ + if(pstrM2MAPConfig == NULL) + { + M2M_ERR("INVALID POINTER\n"); + s8Ret = M2M_ERR_FAIL; + goto ERR1; + } + /* Check for SSID */ + if((m2m_strlen((uint8 *)pstrM2MAPConfig->au8SSID) <= 0) || (m2m_strlen((uint8 *)pstrM2MAPConfig->au8SSID) >= M2M_MAX_SSID_LEN)) + { + M2M_ERR("INVALID SSID\n"); + s8Ret = M2M_ERR_FAIL; + goto ERR1; + } + /* Check for Channel */ + if(pstrM2MAPConfig->u8ListenChannel > M2M_WIFI_CH_14 || pstrM2MAPConfig->u8ListenChannel < M2M_WIFI_CH_1) + { + M2M_ERR("INVALID CH\n"); + s8Ret = M2M_ERR_FAIL; + goto ERR1; + } + /* Check for DHCP Server IP address */ + if(!(pstrM2MAPConfig->au8DHCPServerIP[0] || pstrM2MAPConfig->au8DHCPServerIP[1])) + { + if(!(pstrM2MAPConfig->au8DHCPServerIP[2])) + { + M2M_ERR("INVALID DHCP SERVER IP\n"); + s8Ret = M2M_ERR_FAIL; + goto ERR1; + } + } + /* Check for Security */ + if(pstrM2MAPConfig->u8SecType == M2M_WIFI_SEC_OPEN) + { + goto ERR1; + } + else if(pstrM2MAPConfig->u8SecType == M2M_WIFI_SEC_WEP) + { + /* Check for WEP Key index */ + if((pstrM2MAPConfig->u8KeyIndx <= 0) || (pstrM2MAPConfig->u8KeyIndx > WEP_KEY_MAX_INDEX)) + { + M2M_ERR("INVALID KEY INDEX\n"); + s8Ret = M2M_ERR_FAIL; + goto ERR1; + } + /* Check for WEP Key size */ + if( (pstrM2MAPConfig->u8KeySz != WEP_40_KEY_STRING_SIZE) && + (pstrM2MAPConfig->u8KeySz != WEP_104_KEY_STRING_SIZE) + ) + { + M2M_ERR("INVALID KEY STRING SIZE\n"); + s8Ret = M2M_ERR_FAIL; + goto ERR1; + } + + if((m2m_strlen((uint8 *)pstrM2MAPConfig->au8WepKey) <= 0) || (m2m_strlen((uint8 *)pstrM2MAPConfig->au8WepKey) > WEP_104_KEY_STRING_SIZE)) + { + M2M_ERR("INVALID KEY SIZE\n"); + s8Ret = M2M_ERR_FAIL; + goto ERR1; + } + } + else if(pstrM2MAPConfig->u8SecType == M2M_WIFI_SEC_WPA_PSK) + { + /* Check for WPA Key size */ + if( ((pstrM2MAPConfig->u8KeySz + 1) < M2M_MIN_PSK_LEN) || ((pstrM2MAPConfig->u8KeySz + 1) > M2M_MAX_PSK_LEN)) + { + M2M_ERR("INVALID WPA KEY SIZE\n"); + s8Ret = M2M_ERR_FAIL; + goto ERR1; + } + } + else + { + M2M_ERR("INVALID AUTHENTICATION MODE\n"); + s8Ret = M2M_ERR_FAIL; + goto ERR1; + } + +ERR1: + return s8Ret; +} +static sint8 m2m_validate_scan_options(tstrM2MScanOption* ptstrM2MScanOption) +{ + sint8 s8Ret = M2M_SUCCESS; + /* Check for incoming pointer */ + if(ptstrM2MScanOption == NULL) + { + M2M_ERR("INVALID POINTER\n"); + s8Ret = M2M_ERR_FAIL; + goto ERR; + } + /* Check for valid No of slots */ + if(ptstrM2MScanOption->u8NumOfSlot == 0) + { + M2M_ERR("INVALID No of scan slots! %d\n",ptstrM2MScanOption->u8NumOfSlot); + s8Ret = M2M_ERR_FAIL; + goto ERR; + } + /* Check for valid time of slots */ + if(ptstrM2MScanOption->u8SlotTime < 10 || ptstrM2MScanOption->u8SlotTime > 250) + { + M2M_ERR("INVALID scan slot time! %d\n",ptstrM2MScanOption->u8SlotTime); + s8Ret = M2M_ERR_FAIL; + goto ERR; + } + /* Check for valid No of probe requests per slot */ + if((ptstrM2MScanOption->u8ProbesPerSlot == 0)||(ptstrM2MScanOption->u8ProbesPerSlot > M2M_SCAN_DEFAULT_NUM_PROBE)) + { + M2M_ERR("INVALID No of probe requests per scan slot %d\n",ptstrM2MScanOption->u8ProbesPerSlot); + s8Ret = M2M_ERR_FAIL; + goto ERR; + } + /* Check for valid RSSI threshold */ + if((ptstrM2MScanOption->s8RssiThresh < -99) || (ptstrM2MScanOption->s8RssiThresh >= 0)) + { + M2M_ERR("INVALID RSSI threshold %d \n",ptstrM2MScanOption->s8RssiThresh); + s8Ret = M2M_ERR_FAIL; + } + +ERR: + return s8Ret; +} + +sint8 m2m_wifi_send_crl(tstrTlsCrlInfo* pCRL) +{ + sint8 s8Ret = M2M_ERR_FAIL; + s8Ret = hif_send(M2M_REQ_GROUP_SSL, M2M_SSL_IND_CRL|M2M_REQ_DATA_PKT, NULL, 0, (uint8*)pCRL, sizeof(tstrTlsCrlInfo), 0); + return s8Ret; +} + +sint8 m2m_wifi_init(tstrWifiInitParam * param) +{ + tstrM2mRev strtmp; + sint8 ret = M2M_SUCCESS; + uint8 u8WifiMode = M2M_WIFI_MODE_NORMAL; + + if(param == NULL) { + ret = M2M_ERR_FAIL; + goto _EXIT0; + } + + gpfAppWifiCb = param->pfAppWifiCb; + +#ifdef ETH_MODE + gpfAppEthCb = param->strEthInitParam.pfAppEthCb; + gau8ethRcvBuf = param->strEthInitParam.au8ethRcvBuf; + gu16ethRcvBufSize = param->strEthInitParam.u16ethRcvBufSize; + u8WifiMode = param->strEthInitParam.u8EthernetEnable; +#endif /* ETH_MODE */ + +#ifdef CONF_MGMT + gpfAppMonCb = param->pfAppMonCb; +#endif + gu8scanInProgress = 0; + /* Apply device specific initialization. */ + ret = nm_drv_init(&u8WifiMode); + if(ret != M2M_SUCCESS) goto _EXIT0; + /* Initialize host interface module */ + ret = hif_init(NULL); + if(ret != M2M_SUCCESS) goto _EXIT1; + + hif_register_cb(M2M_REQ_GROUP_WIFI,m2m_wifi_cb); + + ret = nm_get_firmware_full_info(&strtmp); + + M2M_INFO("Firmware ver : %u.%u.%u Svnrev %u\n", strtmp.u8FirmwareMajor, strtmp.u8FirmwareMinor, strtmp.u8FirmwarePatch,strtmp.u16FirmwareSvnNum); + M2M_INFO("Firmware Build %s Time %s\n",strtmp.BuildDate,strtmp.BuildTime); + M2M_INFO("Firmware Min driver ver : %u.%u.%u\n", strtmp.u8DriverMajor, strtmp.u8DriverMinor, strtmp.u8DriverPatch); + M2M_INFO("Driver ver: %u.%u.%u\n", M2M_RELEASE_VERSION_MAJOR_NO, M2M_RELEASE_VERSION_MINOR_NO, M2M_RELEASE_VERSION_PATCH_NO); + M2M_INFO("Driver built at %s\t%s\n",__DATE__,__TIME__); + if(M2M_ERR_FW_VER_MISMATCH == ret) + { + M2M_ERR("Mismatch Firmawre Version\n"); + } + + goto _EXIT0; + +_EXIT1: + nm_drv_deinit(NULL); +_EXIT0: + return ret; +} + +sint8 m2m_wifi_deinit(void * arg) +{ + + hif_deinit(NULL); + + nm_drv_deinit(NULL); + + return M2M_SUCCESS; +} + + +sint8 m2m_wifi_handle_events(void * arg) +{ + return hif_handle_isr(); +} + +sint8 m2m_wifi_default_connect(void) +{ + return hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_DEFAULT_CONNECT, NULL, 0,NULL, 0,0); +} + +sint8 m2m_wifi_connect(char *pcSsid, uint8 u8SsidLen, uint8 u8SecType, void *pvAuthInfo, uint16 u16Ch) +{ + return m2m_wifi_connect_sc(pcSsid, u8SsidLen, u8SecType, pvAuthInfo, u16Ch,0); +} +sint8 m2m_wifi_connect_sc(char *pcSsid, uint8 u8SsidLen, uint8 u8SecType, void *pvAuthInfo, uint16 u16Ch, uint8 u8NoSaveCred) +{ + sint8 ret = M2M_SUCCESS; + tstrM2mWifiConnect strConnect; + tstrM2MWifiSecInfo *pstrAuthInfo; + + if(u8SecType != M2M_WIFI_SEC_OPEN) + { + if(pvAuthInfo == NULL) + { + M2M_ERR("Key is not valid\n"); + ret = M2M_ERR_FAIL; + goto ERR1; + } + if((u8SecType == M2M_WIFI_SEC_WPA_PSK) && (m2m_strlen(pvAuthInfo) == (M2M_MAX_PSK_LEN-1))) + { + uint8 i = 0; + uint8* pu8Psk = (uint8*)pvAuthInfo; + while(i < (M2M_MAX_PSK_LEN-1)) + { + if(pu8Psk[i]<'0' || (pu8Psk[i]>'9' && pu8Psk[i] < 'A')|| (pu8Psk[i]>'F' && pu8Psk[i] < 'a') || pu8Psk[i] > 'f') + { + M2M_ERR("Invalid Key\n"); + ret = M2M_ERR_FAIL; + goto ERR1; + } + i++; + } + } + } + if((u8SsidLen<=0)||(u8SsidLen>=M2M_MAX_SSID_LEN)) + { + M2M_ERR("SSID LEN INVALID\n"); + ret = M2M_ERR_FAIL; + goto ERR1; + } + + if(u16Ch < M2M_WIFI_CH_1|| u16Ch > M2M_WIFI_CH_14) + { + if(u16Ch!=M2M_WIFI_CH_ALL) + { + M2M_ERR("CH INVALID\n"); + ret = M2M_ERR_FAIL; + goto ERR1; + } + } + + + m2m_memcpy(strConnect.au8SSID, (uint8*)pcSsid, u8SsidLen); + strConnect.au8SSID[u8SsidLen] = 0; + strConnect.u16Ch = NM_BSP_B_L_16(u16Ch); + /* Credentials will be Not be saved if u8NoSaveCred is set */ + strConnect.u8NoSaveCred = u8NoSaveCred ? 1:0; + pstrAuthInfo = &strConnect.strSec; + pstrAuthInfo->u8SecType = u8SecType; + + if(u8SecType == M2M_WIFI_SEC_WEP) + { + tstrM2mWifiWepParams * pstrWepParams = (tstrM2mWifiWepParams*)pvAuthInfo; + tstrM2mWifiWepParams *pstrWep = &pstrAuthInfo->uniAuth.strWepInfo; + pstrWep->u8KeyIndx =pstrWepParams->u8KeyIndx-1; + + if(pstrWep->u8KeyIndx >= WEP_KEY_MAX_INDEX) + { + M2M_ERR("Invalid Wep key index %d\n", pstrWep->u8KeyIndx); + ret = M2M_ERR_FAIL; + goto ERR1; + } + pstrWep->u8KeySz = pstrWepParams->u8KeySz-1; + if ((pstrWep->u8KeySz != WEP_40_KEY_STRING_SIZE)&& (pstrWep->u8KeySz != WEP_104_KEY_STRING_SIZE)) + { + M2M_ERR("Invalid Wep key length %d\n", pstrWep->u8KeySz); + ret = M2M_ERR_FAIL; + goto ERR1; + } + m2m_memcpy((uint8*)pstrWep->au8WepKey,(uint8*)pstrWepParams->au8WepKey, pstrWepParams->u8KeySz); + pstrWep->au8WepKey[pstrWepParams->u8KeySz] = 0; + + } + + + else if(u8SecType == M2M_WIFI_SEC_WPA_PSK) + { + uint16 u16KeyLen = m2m_strlen((uint8*)pvAuthInfo); + if((u16KeyLen <= 0)||(u16KeyLen >= M2M_MAX_PSK_LEN)) + { + M2M_ERR("Incorrect PSK key length\n"); + ret = M2M_ERR_FAIL; + goto ERR1; + } + m2m_memcpy(pstrAuthInfo->uniAuth.au8PSK, (uint8*)pvAuthInfo, u16KeyLen + 1); + } + else if(u8SecType == M2M_WIFI_SEC_802_1X) + { + m2m_memcpy((uint8*)&pstrAuthInfo->uniAuth.strCred1x, (uint8*)pvAuthInfo, sizeof(tstr1xAuthCredentials)); + } + else if(u8SecType == M2M_WIFI_SEC_OPEN) + { + + } + else + { + M2M_ERR("undefined sec type\n"); + ret = M2M_ERR_FAIL; + goto ERR1; + } + + ret = hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_CONNECT, (uint8*)&strConnect, sizeof(tstrM2mWifiConnect),NULL, 0,0); + +ERR1: + return ret; +} + +sint8 m2m_wifi_disconnect(void) +{ + return hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_DISCONNECT, NULL, 0, NULL, 0,0); +} +sint8 m2m_wifi_set_mac_address(uint8 au8MacAddress[6]) +{ + tstrM2mSetMacAddress strTmp; + m2m_memcpy((uint8*) strTmp.au8Mac, (uint8*) au8MacAddress, 6); + return hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_SET_MAC_ADDRESS, + (uint8*) &strTmp, sizeof(tstrM2mSetMacAddress), NULL, 0,0); +} + +sint8 m2m_wifi_set_static_ip(tstrM2MIPConfig * pstrStaticIPConf) +{ + pstrStaticIPConf->u32DNS = NM_BSP_B_L_32(pstrStaticIPConf->u32DNS); + pstrStaticIPConf->u32Gateway = NM_BSP_B_L_32(pstrStaticIPConf->u32Gateway); + pstrStaticIPConf->u32StaticIP = NM_BSP_B_L_32( + pstrStaticIPConf->u32StaticIP); + pstrStaticIPConf->u32SubnetMask = NM_BSP_B_L_32( + pstrStaticIPConf->u32SubnetMask); + return hif_send(M2M_REQ_GROUP_IP, M2M_IP_REQ_STATIC_IP_CONF, + (uint8*) pstrStaticIPConf, sizeof(tstrM2MIPConfig), NULL, 0,0); +} + +sint8 m2m_wifi_request_dhcp_client(void) +{ + /*legacy API should be removed */ + return 0; +} +sint8 m2m_wifi_request_dhcp_server(uint8* addr) +{ + /*legacy API should be removed */ + return 0; +} +/*! +@fn NMI_API sint8 m2m_wifi_set_lsn_int(tstrM2mLsnInt * pstrM2mLsnInt); +@brief Set the Wi-Fi listen interval for power save operation. It is represented in units + of AP Beacon periods. +@param [in] pstrM2mLsnInt + Structure holding the listen interval configurations. +@return The function SHALL return 0 for success and a negative value otherwise. +@sa tstrM2mLsnInt , m2m_wifi_set_sleep_mode +@pre m2m_wifi_set_sleep_mode shall be called first +@warning The Function called once after initialization. +*/ +sint8 m2m_wifi_enable_dhcp(uint8 u8DhcpEn ) +{ + + uint8 u8Req; + u8Req = u8DhcpEn ? M2M_IP_REQ_ENABLE_DHCP : M2M_IP_REQ_DISABLE_DHCP; + return hif_send(M2M_REQ_GROUP_IP, u8Req, NULL, 0, NULL, 0, 0); + + +} + +sint8 m2m_wifi_set_lsn_int(tstrM2mLsnInt* pstrM2mLsnInt) +{ + return hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_LSN_INT, (uint8*)pstrM2mLsnInt, sizeof(tstrM2mLsnInt), NULL, 0, 0); +} + +sint8 m2m_wifi_set_cust_InfoElement(uint8* pau8M2mCustInfoElement) +{ + + sint8 ret = M2M_ERR_FAIL; + if(pau8M2mCustInfoElement != NULL) + { + if((pau8M2mCustInfoElement[0] + 1) < M2M_CUST_IE_LEN_MAX) + { + ret = hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_CUST_INFO_ELEMENT|M2M_REQ_DATA_PKT, (uint8*)pau8M2mCustInfoElement, pau8M2mCustInfoElement[0]+1, NULL, 0, 0); + } + } + return ret; +} + +sint8 m2m_wifi_set_scan_options(tstrM2MScanOption* ptstrM2MScanOption) +{ + sint8 s8Ret = M2M_ERR_FAIL; + if(m2m_validate_scan_options (ptstrM2MScanOption) == M2M_SUCCESS) + { + s8Ret = hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_SET_SCAN_OPTION, (uint8*)ptstrM2MScanOption, sizeof(tstrM2MScanOption),NULL, 0,0); + } + return s8Ret; +} +sint8 m2m_wifi_set_scan_region(uint16 ScanRegion) +{ + sint8 s8Ret = M2M_ERR_FAIL; + tstrM2MScanRegion strScanRegion; + strScanRegion.u16ScanRegion = ScanRegion; + s8Ret = hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_SET_SCAN_REGION, (uint8*)&strScanRegion, sizeof(tstrM2MScanRegion),NULL, 0,0); + return s8Ret; +} +sint8 m2m_wifi_request_scan(uint8 ch) +{ + sint8 s8Ret = M2M_SUCCESS; + + if(!gu8scanInProgress) + { + if(((ch >= M2M_WIFI_CH_1) && (ch <= M2M_WIFI_CH_14)) || (ch == M2M_WIFI_CH_ALL)) + { + tstrM2MScan strtmp; + strtmp.u8ChNum = ch; + s8Ret = hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_SCAN, (uint8*)&strtmp, sizeof(tstrM2MScan),NULL, 0,0); + if(s8Ret == M2M_SUCCESS) + { + gu8scanInProgress = 1; + } + } + else + { + s8Ret = M2M_ERR_INVALID_ARG; + } + } + else + { + s8Ret = M2M_ERR_SCAN_IN_PROGRESS; + } + return s8Ret; +} + +sint8 m2m_wifi_request_scan_passive(uint8 ch, uint16 scan_time) +{ + sint8 s8Ret = M2M_SUCCESS; + + if(!gu8scanInProgress) + { + if(((ch >= M2M_WIFI_CH_1) && (ch <= M2M_WIFI_CH_14)) || (ch == M2M_WIFI_CH_ALL)) + { + tstrM2MScan strtmp; + strtmp.u8ChNum = ch; + + strtmp.u16PassiveScanTime = scan_time; + + s8Ret = hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_PASSIVE_SCAN, (uint8*)&strtmp, sizeof(tstrM2MScan),NULL, 0,0); + if(s8Ret == M2M_SUCCESS) + { + gu8scanInProgress = 1; + } + } + else + { + s8Ret = M2M_ERR_INVALID_ARG; + } + } + else + { + s8Ret = M2M_ERR_SCAN_IN_PROGRESS; + } + return s8Ret; +} + +sint8 m2m_wifi_request_scan_ssid_list(uint8 ch,uint8 * u8Ssidlist) +{ + sint8 s8Ret = M2M_ERR_INVALID_ARG; + + if(!gu8scanInProgress) + { + if((((ch >= M2M_WIFI_CH_1) && (ch <= M2M_WIFI_CH_14)) || (ch == M2M_WIFI_CH_ALL))&&(u8Ssidlist != NULL)) + { + tstrM2MScan strtmp; + uint16 u16Lsize = 0; + uint8 u8Apnum = u8Ssidlist[u16Lsize]; + if(u8Apnum <= MAX_HIDDEN_SITES) + { + u16Lsize++; + while(u8Apnum) + { + if(u8Ssidlist[u16Lsize] >= M2M_MAX_SSID_LEN){ + goto EXIT; + }else { + u16Lsize += u8Ssidlist[u16Lsize] + 1; + u8Apnum--; + } + } + strtmp.u8ChNum = ch; + s8Ret = hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_SCAN_SSID_LIST|M2M_REQ_DATA_PKT, (uint8*)&strtmp, sizeof(tstrM2MScan),u8Ssidlist, u16Lsize,sizeof(tstrM2MScan)); + if(s8Ret == M2M_SUCCESS) + { + gu8scanInProgress = 1; + } + } + } + } + else + { + s8Ret = M2M_ERR_SCAN_IN_PROGRESS; + } +EXIT: + return s8Ret; +} +sint8 m2m_wifi_wps(uint8 u8TriggerType,const char *pcPinNumber) +{ + tstrM2MWPSConnect strtmp; + + /* Stop Scan if it is ongoing. + */ + gu8scanInProgress = 0; + strtmp.u8TriggerType = u8TriggerType; + /*If WPS is using PIN METHOD*/ + if (u8TriggerType == WPS_PIN_TRIGGER) + m2m_memcpy ((uint8*)strtmp.acPinNumber,(uint8*) pcPinNumber,8); + return hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_WPS, (uint8*)&strtmp,sizeof(tstrM2MWPSConnect), NULL, 0,0); +} +sint8 m2m_wifi_wps_disable(void) +{ + sint8 ret = M2M_SUCCESS; + ret = hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_DISABLE_WPS, NULL,0, NULL, 0, 0); + return ret; +} +/*! +@fn NMI_API sint8 m2m_wifi_req_client_ctrl(uint8 cmd); +@brief Send a command to the PS Client (An WINC1500 board running the ps_firmware), + if the PS client send any commands it will be received in wifi_cb M2M_WIFI_RESP_CLIENT_INFO +@param [in] cmd + Control command sent from PS Server to PS Client (command values defined by the application) +@return The function SHALL return M2M_SUCCESE for success and a negative value otherwise. +@sa m2m_wifi_req_server_init, M2M_WIFI_RESP_CLIENT_INFO +@pre m2m_wifi_req_server_init should be called first +@warning +*/ +sint8 m2m_wifi_req_client_ctrl(uint8 u8Cmd) +{ + + sint8 ret = M2M_SUCCESS; +#ifdef _PS_SERVER_ + tstrM2Mservercmd strCmd; + strCmd.u8cmd = u8Cmd; + ret = hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_CLIENT_CTRL, (uint8*)&strCmd, sizeof(tstrM2Mservercmd), NULL, 0, 0); +#else + M2M_ERR("_PS_SERVER_ is not defined\n"); +#endif + return ret; +} +/*! +@fn NMI_API sint8 m2m_wifi_req_server_init(uint8 ch); +@brief Initialize the PS Server, The WINC1500 support Non secure communication with another WINC1500, + (SERVER/CLIENT) through one byte command (probe request and probe response) without any connection setup +@param [in] ch + Server listening channel +@return The function SHALL return M2M_SUCCESE for success and a negative value otherwise +@sa m2m_wifi_req_client_ctrl +@warning The server mode can't be used with any other modes (STA/P2P/AP) +*/ +sint8 m2m_wifi_req_server_init(uint8 ch) +{ + sint8 ret = M2M_SUCCESS; +#ifdef _PS_SERVER_ + tstrM2mServerInit strServer; + strServer.u8Channel = ch; + ret = hif_send(M2M_REQ_GROUP_WIFI,M2M_WIFI_REQ_SERVER_INIT, (uint8*)&strServer, sizeof(tstrM2mServerInit), NULL, 0, 0); +#else + M2M_ERR("_PS_SERVER_ is not defined\n"); +#endif + return ret; +} +sint8 m2m_wifi_p2p(uint8 u8Channel) +{ + sint8 ret = M2M_SUCCESS; + if((u8Channel == M2M_WIFI_CH_1) || (u8Channel == M2M_WIFI_CH_6) || (u8Channel == M2M_WIFI_CH_11)) + { + tstrM2MP2PConnect strtmp; + strtmp.u8ListenChannel = u8Channel; + ret = hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_ENABLE_P2P, (uint8*)&strtmp, sizeof(tstrM2MP2PConnect), NULL, 0,0); + } + else + { + M2M_ERR("Listen channel should only be M2M_WIFI_CH_1/6/11 \n"); + ret = M2M_ERR_FAIL; + } + return ret; +} +sint8 m2m_wifi_p2p_disconnect(void) +{ + sint8 ret = M2M_SUCCESS; + ret = hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_DISABLE_P2P, NULL, 0, NULL, 0, 0); + return ret; +} +sint8 m2m_wifi_enable_ap(CONST tstrM2MAPConfig* pstrM2MAPConfig) +{ + sint8 ret = M2M_ERR_FAIL; + if(M2M_SUCCESS == m2m_validate_ap_parameters(pstrM2MAPConfig)) + { + ret = hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_ENABLE_AP, (uint8 *)pstrM2MAPConfig, sizeof(tstrM2MAPConfig), NULL, 0, 0); + } + return ret; +} + +sint8 m2m_wifi_set_gains(tstrM2mWifiGainsParams* pstrM2mGain) +{ + sint8 ret = M2M_ERR_FAIL; + if(pstrM2mGain != NULL) + { + ret = hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_SET_GAINS, (uint8 *)pstrM2mGain, sizeof(tstrM2mWifiGainsParams), NULL, 0, 0); + } + return ret; +} +sint8 m2m_wifi_disable_ap(void) +{ + sint8 ret = M2M_SUCCESS; + ret = hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_DISABLE_AP, NULL, 0, NULL, 0, 0); + return ret; +} +/*! +@fn NMI_API sint8 m2m_wifi_req_curr_rssi(void); +@brief Request the current RSSI for the current connected AP, + the response received in wifi_cb M2M_WIFI_RESP_CURRENT_RSSI +@sa M2M_WIFI_RESP_CURRENT_RSSI +@return The function shall return M2M_SUCCESS for success and a negative value otherwise. +*/ +sint8 m2m_wifi_req_curr_rssi(void) +{ + sint8 ret = M2M_SUCCESS; + ret = hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_CURRENT_RSSI, NULL, 0, NULL,0, 0); + return ret; +} +sint8 m2m_wifi_send_ethernet_pkt(uint8* pu8Packet,uint16 u16PacketSize) +{ + sint8 s8Ret = -1; + if((pu8Packet != NULL)&&(u16PacketSize>0)) + { + tstrM2MWifiTxPacketInfo strTxPkt; + + strTxPkt.u16PacketSize = u16PacketSize; + strTxPkt.u16HeaderLength = M2M_ETHERNET_HDR_LEN; + s8Ret = hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_SEND_ETHERNET_PACKET | M2M_REQ_DATA_PKT, + (uint8*)&strTxPkt, sizeof(tstrM2MWifiTxPacketInfo), pu8Packet, u16PacketSize, M2M_ETHERNET_HDR_OFFSET - M2M_HIF_HDR_OFFSET); + } + return s8Ret; +} +/*! +@fn NMI_API sint8 m2m_wifi_get_otp_mac_address(uint8 *pu8MacAddr, uint8 * pu8IsValid); +@brief Request the MAC address stored on the OTP (one time programmable) memory of the device. + (the function is Blocking until response received) +@param [out] pu8MacAddr + Output MAC address buffer of 6 bytes size. Valid only if *pu8Valid=1. +@param [out] pu8IsValid + A output boolean value to indicate the validity of pu8MacAddr in OTP. + Output zero if the OTP memory is not programmed, non-zero otherwise. +@return The function shall return M2M_SUCCESS for success and a negative value otherwise. +@sa m2m_wifi_get_mac_address +@pre m2m_wifi_init required to call any WIFI/socket function +*/ +sint8 m2m_wifi_get_otp_mac_address(uint8 *pu8MacAddr, uint8* pu8IsValid) +{ + sint8 ret = M2M_SUCCESS; + ret = hif_chip_wake(); + if(ret == M2M_SUCCESS) + { + ret = nmi_get_otp_mac_address(pu8MacAddr, pu8IsValid); + if(ret == M2M_SUCCESS) + { + ret = hif_chip_sleep(); + } + } + return ret; +} +/*! +@fn NMI_API sint8 m2m_wifi_get_mac_address(uint8 *pu8MacAddr) +@brief Request the current MAC address of the device (the working mac address). + (the function is Blocking until response received) +@param [out] pu8MacAddr + Output MAC address buffer of 6 bytes size. +@return The function shall return M2M_SUCCESS for success and a negative value otherwise. +@sa m2m_wifi_get_otp_mac_address +@pre m2m_wifi_init required to call any WIFI/socket function +*/ +sint8 m2m_wifi_get_mac_address(uint8 *pu8MacAddr) +{ + sint8 ret = M2M_SUCCESS; + ret = hif_chip_wake(); + if(ret == M2M_SUCCESS) + { + ret = nmi_get_mac_address(pu8MacAddr); + if(ret == M2M_SUCCESS) + { + ret = hif_chip_sleep(); + } + } + + return ret; +} +/*! +@fn NMI_API sint8 m2m_wifi_req_scan_result(uint8 index); +@brief Reads the AP information from the Scan Result list with the given index, + the response received in wifi_cb M2M_WIFI_RESP_SCAN_RESULT, + the response pointer should be casted with tstrM2mWifiscanResult structure +@param [in] index + Index for the requested result, the index range start from 0 till number of AP's found +@sa tstrM2mWifiscanResult,m2m_wifi_get_num_ap_found,m2m_wifi_request_scan +@return The function shall return M2M_SUCCESE for success and a negative value otherwise +@pre m2m_wifi_request_scan need to be called first, then m2m_wifi_get_num_ap_found + to get the number of AP's found +@warning Function used only in STA mode only. the scan result updated only if scan request called, + else it will be cashed in firmware for the host scan request result, + which mean if large delay occur between the scan request and the scan result request, + the result will not be up-to-date +*/ + +sint8 m2m_wifi_req_scan_result(uint8 index) +{ + sint8 ret = M2M_SUCCESS; + tstrM2mReqScanResult strReqScanRlt; + strReqScanRlt.u8Index = index; + ret = hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_SCAN_RESULT, (uint8*) &strReqScanRlt, sizeof(tstrM2mReqScanResult), NULL, 0, 0); + return ret; +} +/*! +@fn NMI_API uint8 m2m_wifi_get_num_ap_found(void); +@brief Reads the number of AP's found in the last Scan Request, + The function read the number of AP's from global variable which updated in the + wifi_cb in M2M_WIFI_RESP_SCAN_DONE. +@sa m2m_wifi_request_scan +@return Return the number of AP's found in the last Scan Request. +@pre m2m_wifi_request_scan need to be called first +@warning That function need to be called in the wifi_cb in M2M_WIFI_RESP_SCAN_DONE, + calling that function in any other place will return undefined/undated numbers. + Function used only in STA mode only. +*/ +uint8 m2m_wifi_get_num_ap_found(void) +{ + return gu8ChNum; +} +/*! +@fn NMI_API uint8 m2m_wifi_get_sleep_mode(void); +@brief Get the current Power save mode. +@return The current operating power saving mode. +@sa tenuPowerSaveModes , m2m_wifi_set_sleep_mode +*/ +uint8 m2m_wifi_get_sleep_mode(void) +{ + return hif_get_sleep_mode(); +} +/*! +@fn NMI_API sint8 m2m_wifi_set_sleep_mode(uint8 PsTyp, uint8 BcastEn); +@brief Set the power saving mode for the WINC1500. +@param [in] PsTyp + Desired power saving mode. Supported types are defined in tenuPowerSaveModes. +@param [in] BcastEn + Broadcast reception enable flag. + If it is 1, the WINC1500 must be awake each DTIM Beacon for receiving Broadcast traffic. + If it is 0, the WINC1500 will not wakeup at the DTIM Beacon, but its wakeup depends only + on the the configured Listen Interval. +@return The function SHALL return 0 for success and a negative value otherwise. +@sa tenuPowerSaveModes +@warning The function called once after initialization. +*/ +sint8 m2m_wifi_set_sleep_mode(uint8 PsTyp, uint8 BcastEn) +{ + sint8 ret = M2M_SUCCESS; + tstrM2mPsType strPs; + strPs.u8PsType = PsTyp; + strPs.u8BcastEn = BcastEn; + ret = hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_SLEEP, (uint8*) &strPs,sizeof(tstrM2mPsType), NULL, 0, 0); + M2M_INFO("POWER SAVE %d\n",PsTyp); + hif_set_sleep_mode(PsTyp); + return ret; +} +/*! +@fn NMI_API sint8 m2m_wifi_request_sleep(void) +@brief Request from WINC1500 device to Sleep for specific time in the M2M_PS_MANUAL Power save mode (only). +@param [in] u32SlpReqTime + Request Sleep in ms +@return The function SHALL return M2M_SUCCESS for success and a negative value otherwise. +@sa tenuPowerSaveModes , m2m_wifi_set_sleep_mode +@warning the Function should be called in M2M_PS_MANUAL power save only +*/ +sint8 m2m_wifi_request_sleep(uint32 u32SlpReqTime) +{ + sint8 ret = M2M_SUCCESS; + uint8 psType; + psType = hif_get_sleep_mode(); + if(psType == M2M_PS_MANUAL) + { + tstrM2mSlpReqTime strPs; + strPs.u32SleepTime = u32SlpReqTime; + ret = hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_DOZE, (uint8*) &strPs,sizeof(tstrM2mSlpReqTime), NULL, 0, 0); + } + return ret; +} +/*! +@fn NMI_API sint8 m2m_wifi_set_device_name(uint8 *pu8DeviceName, uint8 u8DeviceNameLength); +@brief Set the WINC1500 device name which is used as P2P device name. +@param [in] pu8DeviceName + Buffer holding the device name. +@param [in] u8DeviceNameLength + Length of the device name. +@return The function SHALL return M2M_SUCCESS for success and a negative value otherwise. +@warning The Function called once after initialization. +*/ +sint8 m2m_wifi_set_device_name(uint8 *pu8DeviceName, uint8 u8DeviceNameLength) +{ + tstrM2MDeviceNameConfig strDeviceName; + if(u8DeviceNameLength >= M2M_DEVICE_NAME_MAX) + { + u8DeviceNameLength = M2M_DEVICE_NAME_MAX; + } + //pu8DeviceName[u8DeviceNameLength] = '\0'; + u8DeviceNameLength ++; + m2m_memcpy(strDeviceName.au8DeviceName, pu8DeviceName, u8DeviceNameLength); + return hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_SET_DEVICE_NAME, + (uint8*)&strDeviceName, sizeof(tstrM2MDeviceNameConfig), NULL, 0,0); +} +sint8 m2m_wifi_get_firmware_version(tstrM2mRev *pstrRev) +{ + sint8 ret = M2M_SUCCESS; + ret = hif_chip_wake(); + if(ret == M2M_SUCCESS) + { + ret = nm_get_firmware_full_info(pstrRev); + hif_chip_sleep(); + } + return ret; +} +#ifdef CONF_MGMT +sint8 m2m_wifi_enable_monitoring_mode(tstrM2MWifiMonitorModeCtrl *pstrMtrCtrl, uint8 *pu8PayloadBuffer, + uint16 u16BufferSize, uint16 u16DataOffset) +{ + sint8 s8Ret = -1; + if((pstrMtrCtrl->u8ChannelID >= M2M_WIFI_CH_1) && (pstrMtrCtrl->u8ChannelID <= M2M_WIFI_CH_14)) + { + gstrMgmtCtrl.pu8Buf = pu8PayloadBuffer; + gstrMgmtCtrl.u16Sz = u16BufferSize; + gstrMgmtCtrl.u16Offset = u16DataOffset; + s8Ret = hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_ENABLE_MONITORING, + (uint8*)pstrMtrCtrl, sizeof(tstrM2MWifiMonitorModeCtrl), NULL, 0,0); + } + return s8Ret; +} + +sint8 m2m_wifi_disable_monitoring_mode(void) +{ + return hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_DISABLE_MONITORING, NULL, 0, NULL, 0,0); +} + +sint8 m2m_wifi_send_wlan_pkt(uint8 *pu8WlanPacket, uint16 u16WlanHeaderLength, uint16 u16WlanPktSize) +{ + sint8 s8Ret = -1; + if(pu8WlanPacket != NULL) + { + tstrM2MWifiTxPacketInfo strTxPkt; + + strTxPkt.u16PacketSize = u16WlanPktSize; + strTxPkt.u16HeaderLength = u16WlanHeaderLength; + s8Ret = hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_SEND_WIFI_PACKET | M2M_REQ_DATA_PKT, + (uint8*)&strTxPkt, sizeof(tstrM2MWifiTxPacketInfo), pu8WlanPacket, u16WlanPktSize, sizeof(tstrM2MWifiTxPacketInfo)); + } + return s8Ret; +} +#endif + +sint8 m2m_wifi_start_provision_mode(tstrM2MAPConfig *pstrAPConfig, char *pcHttpServerDomainName, uint8 bEnableHttpRedirect) +{ + sint8 s8Ret = M2M_ERR_FAIL; + + if((pstrAPConfig != NULL)) + { + tstrM2MProvisionModeConfig strProvConfig; + if(M2M_SUCCESS == m2m_validate_ap_parameters(pstrAPConfig)) + { + m2m_memcpy((uint8*)&strProvConfig.strApConfig, (uint8*)pstrAPConfig, sizeof(tstrM2MAPConfig)); + if((m2m_strlen((uint8 *)pcHttpServerDomainName) <= 0) || (NULL == pcHttpServerDomainName)) + { + M2M_ERR("INVALID DOMAIN NAME\n"); + goto ERR1; + } + m2m_memcpy((uint8*)strProvConfig.acHttpServerDomainName, (uint8*)pcHttpServerDomainName, 64); + strProvConfig.u8EnableRedirect = bEnableHttpRedirect; + + /* Stop Scan if it is ongoing. + */ + gu8scanInProgress = 0; + s8Ret = hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_START_PROVISION_MODE | M2M_REQ_DATA_PKT, + (uint8*)&strProvConfig, sizeof(tstrM2MProvisionModeConfig), NULL, 0, 0); + } + else + { + /*goto ERR1;*/ + } + } +ERR1: + return s8Ret; +} + +sint8 m2m_wifi_stop_provision_mode(void) +{ + return hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_STOP_PROVISION_MODE, NULL, 0, NULL, 0, 0); +} + +sint8 m2m_wifi_get_connection_info(void) +{ + return hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_GET_CONN_INFO, NULL, 0, NULL, 0, 0); +} + +sint8 m2m_wifi_set_sytem_time(uint32 u32UTCSeconds) +{ + /* + The firmware accepts timestamps relative to 1900 like NTP Timestamp. + */ + return hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_SET_SYS_TIME, (uint8*)&u32UTCSeconds, sizeof(tstrSystemTime), NULL, 0, 0); +} +/*! + * @fn NMI_API sint8 m2m_wifi_get_sytem_time(void); + * @see m2m_wifi_enable_sntp + tstrSystemTime + * @note get the system time from the sntp client + * using the API \ref m2m_wifi_get_sytem_time. + * @return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. + */ +sint8 m2m_wifi_get_sytem_time(void) +{ + return hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_GET_SYS_TIME, NULL,0, NULL, 0, 0); +} + +sint8 m2m_wifi_enable_sntp(uint8 bEnable) +{ + uint8 u8Req; + + u8Req = bEnable ? M2M_WIFI_REQ_ENABLE_SNTP_CLIENT : M2M_WIFI_REQ_DISABLE_SNTP_CLIENT; + return hif_send(M2M_REQ_GROUP_WIFI, u8Req, NULL, 0, NULL, 0, 0); +} +/*! +@fn NMI_API sint8 m2m_wifi_set_power_profile(uint8 u8PwrMode); +@brief Change the power profile mode +@param [in] u8PwrMode + Change the WINC power profile to different mode + PWR_LOW1/PWR_LOW2/PWR_HIGH/PWR_AUTO (tenuM2mPwrMode) +@return The function SHALL return M2M_SUCCESE for success and a negative value otherwise. +@sa tenuM2mPwrMode +@pre m2m_wifi_init +@warning must be called after the initializations and before any connection request and can't be changed in run time, +*/ +sint8 m2m_wifi_set_power_profile(uint8 u8PwrMode) +{ + sint8 ret = M2M_SUCCESS; + tstrM2mPwrMode strM2mPwrMode; + strM2mPwrMode.u8PwrMode = u8PwrMode; + ret = hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_SET_POWER_PROFILE, (uint8*)&strM2mPwrMode,sizeof(tstrM2mPwrMode), NULL, 0, 0); + return ret; +} +/*! +@fn NMI_API sint8 m2m_wifi_set_tx_power(uint8 u8TxPwrLevel); +@brief set the TX power tenuM2mTxPwrLevel +@param [in] u8TxPwrLevel + change the TX power tenuM2mTxPwrLevel +@return The function SHALL return M2M_SUCCESE for success and a negative value otherwise. +@sa tenuM2mTxPwrLevel +@pre m2m_wifi_init +@warning +*/ +sint8 m2m_wifi_set_tx_power(uint8 u8TxPwrLevel) +{ + sint8 ret = M2M_SUCCESS; + tstrM2mTxPwrLevel strM2mTxPwrLevel; + strM2mTxPwrLevel.u8TxPwrLevel = u8TxPwrLevel; + ret = hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_SET_TX_POWER, (uint8*)&strM2mTxPwrLevel,sizeof(tstrM2mTxPwrLevel), NULL, 0, 0); + return ret; +} + +/*! +@fn NMI_API sint8 m2m_wifi_enable_firmware_logs(uint8 u8Enable); +@brief Enable or Disable logs in run time (Disable Firmware logs will + enhance the firmware start-up time and performance) +@param [in] u8Enable + Set 1 to enable the logs 0 for disable +@return The function SHALL return M2M_SUCCESE for success and a negative value otherwise. +@sa __DISABLE_FIRMWARE_LOGS__ (build option to disable logs from initializations) +@pre m2m_wifi_init +@warning +*/ +sint8 m2m_wifi_enable_firmware_logs(uint8 u8Enable) +{ + sint8 ret = M2M_SUCCESS; + tstrM2mEnableLogs strM2mEnableLogs; + strM2mEnableLogs.u8Enable = u8Enable; + ret = hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_SET_ENABLE_LOGS, (uint8*)&strM2mEnableLogs,sizeof(tstrM2mEnableLogs), NULL, 0, 0); + return ret; +} + +/*! +@fn NMI_API sint8 m2m_wifi_set_battery_voltage(uint16 u16BattVoltx100); +@brief Enable or Disable logs in run time (Disable Firmware logs will + enhance the firmware start-up time and performance) +@param [in] u16BattVoltx100 + battery voltage multiplied by 100 +@return The function SHALL return M2M_SUCCESE for success and a negative value otherwise. +@sa __DISABLE_FIRMWARE_LOGS__ (build option to disable logs from initializations) +@pre m2m_wifi_init +@warning +*/ +sint8 m2m_wifi_set_battery_voltage(uint16 u16BattVoltx100) +{ + sint8 ret = M2M_SUCCESS; + tstrM2mBatteryVoltage strM2mBattVol = {0}; + strM2mBattVol.u16BattVolt = u16BattVoltx100; + ret = hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_SET_BATTERY_VOLTAGE, (uint8*)&strM2mBattVol,sizeof(tstrM2mBatteryVoltage), NULL, 0, 0); + return ret; +} +/*! +@fn sint8 m2m_wifi_prng_get_random_bytes(uint8 * pu8PrngBuff,uint16 u16PrngSize) +@brief Get random bytes using the PRNG bytes. +@param [in] u16PrngSize + Size of the required random bytes to be generated. +@param [in] pu8PrngBuff + Pointer to user allocated buffer. +@return The function SHALL return M2M_SUCCESE for success and a negative value otherwise. +*/ +sint8 m2m_wifi_prng_get_random_bytes(uint8 * pu8PrngBuff,uint16 u16PrngSize) +{ + sint8 ret = M2M_ERR_FAIL; + tstrPrng strRng = {0}; + if((u16PrngSize < (M2M_BUFFER_MAX_SIZE - sizeof(tstrPrng)))&&(pu8PrngBuff != NULL)) + { + strRng.u16PrngSize = u16PrngSize; + strRng.pu8RngBuff = pu8PrngBuff; + ret = hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_GET_PRNG|M2M_REQ_DATA_PKT,(uint8 *)&strRng, sizeof(tstrPrng),NULL,0, 0); + } + else + { + M2M_ERR("PRNG Buffer exceeded maximum size %d or NULL Buffer\n",u16PrngSize); + } + return ret; +} +#ifdef ETH_MODE +/*! +@fn \ + NMI_API sint8 m2m_wifi_enable_mac_mcast(uint8* pu8MulticastMacAddress, uint8 u8AddRemove) + +@brief + Add MAC filter to receive Multicast packets. + +@param [in] pu8MulticastMacAddress + Pointer to the MAC address. +@param [in] u8AddRemove + Flag to Add/Remove MAC address. +@return + The function SHALL return 0 for success and a negative value otherwise. +*/ + +NMI_API sint8 m2m_wifi_enable_mac_mcast(uint8* pu8MulticastMacAddress, uint8 u8AddRemove) +{ + sint8 s8ret = M2M_ERR_FAIL; + tstrM2MMulticastMac strMulticastMac; + + if(pu8MulticastMacAddress != NULL ) + { + strMulticastMac.u8AddRemove = u8AddRemove; + m2m_memcpy(strMulticastMac.au8macaddress,pu8MulticastMacAddress,M2M_MAC_ADDRES_LEN); + M2M_DBG("mac multicast: %x:%x:%x:%x:%x:%x\r\n",strMulticastMac.au8macaddress[0],strMulticastMac.au8macaddress[1],strMulticastMac.au8macaddress[2],strMulticastMac.au8macaddress[3],strMulticastMac.au8macaddress[4],strMulticastMac.au8macaddress[5]); + s8ret = hif_send(M2M_REQ_GROUP_WIFI, M2M_WIFI_REQ_SET_MAC_MCAST, (uint8 *)&strMulticastMac,sizeof(tstrM2MMulticastMac),NULL,0,0); + } + + return s8ret; + +} + +/*! +@fn \ + NMI_API sint8 m2m_wifi_set_receive_buffer(void* pvBuffer,uint16 u16BufferLen); + +@brief + set the ethernet receive buffer, should be called in the receive call back. + +@param [in] pvBuffer + Pointer to the ethernet receive buffer. +@param [in] u16BufferLen + Length of the buffer. + +@return + The function SHALL return 0 for success and a negative value otherwise. +*/ +NMI_API sint8 m2m_wifi_set_receive_buffer(void* pvBuffer,uint16 u16BufferLen) +{ + sint8 s8ret = M2M_SUCCESS; + if(pvBuffer != NULL) + { + gau8ethRcvBuf = pvBuffer; + gu16ethRcvBufSize= u16BufferLen; + } + else + { + s8ret = M2M_ERR_FAIL; + M2M_ERR("Buffer NULL pointer\r\n"); + } + return s8ret; +} +#endif /* ETH_MODE */ diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmasic.c b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmasic.c new file mode 100644 index 0000000000000..54883ff2ec9ab --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmasic.c @@ -0,0 +1,664 @@ +/** + * + * \file + * + * \brief This module contains NMC1500 ASIC specific internal APIs. + * + * Copyright (c) 2016-2017 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + +#include "common/include/nm_common.h" +#include "driver/source/nmbus.h" +#include "bsp/include/nm_bsp.h" +#include "driver/source/nmasic.h" +#include "driver/include/m2m_types.h" + +#define NMI_GLB_RESET_0 (NMI_PERIPH_REG_BASE + 0x400) +#define NMI_INTR_REG_BASE (NMI_PERIPH_REG_BASE + 0xa00) +#define NMI_PIN_MUX_0 (NMI_PERIPH_REG_BASE + 0x408) +#define NMI_INTR_ENABLE (NMI_INTR_REG_BASE) +#define GET_UINT32(X,Y) (X[0+Y] + ((uint32)X[1+Y]<<8) + ((uint32)X[2+Y]<<16) +((uint32)X[3+Y]<<24)) + +/*SPI and I2C only*/ +#define CORT_HOST_COMM (0x10) +#define HOST_CORT_COMM (0x0b) +#define WAKE_CLK_REG (0x1) +#define CLOCKS_EN_REG (0xf) + + + +#define TIMEOUT (0xfffffffful) +#define WAKUP_TRAILS_TIMEOUT (4) + +sint8 chip_apply_conf(uint32 u32Conf) +{ + sint8 ret = M2M_SUCCESS; + uint32 val32 = u32Conf; + +#if (defined __ENABLE_PMU__) || (defined CONF_WINC_INT_PMU) + val32 |= rHAVE_USE_PMU_BIT; +#endif +#ifdef __ENABLE_SLEEP_CLK_SRC_RTC__ + val32 |= rHAVE_SLEEP_CLK_SRC_RTC_BIT; +#elif defined __ENABLE_SLEEP_CLK_SRC_XO__ + val32 |= rHAVE_SLEEP_CLK_SRC_XO_BIT; +#endif +#ifdef __ENABLE_EXT_PA_INV_TX_RX__ + val32 |= rHAVE_EXT_PA_INV_TX_RX; +#endif +#ifdef __ENABLE_LEGACY_RF_SETTINGS__ + val32 |= rHAVE_LEGACY_RF_SETTINGS; +#endif +#ifdef __DISABLE_FIRMWARE_LOGS__ + val32 |= rHAVE_LOGS_DISABLED_BIT; +#endif + + val32 |= rHAVE_RESERVED1_BIT; + do { + nm_write_reg(rNMI_GP_REG_1, val32); + if(val32 != 0) { + uint32 reg = 0; + ret = nm_read_reg_with_ret(rNMI_GP_REG_1, ®); + if(ret == M2M_SUCCESS) { + if(reg == val32) + break; + } + } else { + break; + } + } while(1); + + return M2M_SUCCESS; +} +void chip_idle(void) +{ + uint32 reg = 0; + nm_read_reg_with_ret(WAKE_CLK_REG, ®); + if(reg & NBIT1) + { + reg &=~ NBIT1; + nm_write_reg(WAKE_CLK_REG, reg); + } +} + +sint8 enable_interrupts(void) +{ + uint32 reg = 0; + sint8 ret = M2M_SUCCESS; + /** + interrupt pin mux select + **/ + ret = nm_read_reg_with_ret(NMI_PIN_MUX_0, ®); + if (M2M_SUCCESS != ret) goto ERR1; + + reg |= ((uint32) 1 << 8); + ret = nm_write_reg(NMI_PIN_MUX_0, reg); + if (M2M_SUCCESS != ret) goto ERR1; + + /** + interrupt enable + **/ + ret = nm_read_reg_with_ret(NMI_INTR_ENABLE, ®); + if (M2M_SUCCESS != ret) goto ERR1; + + reg |= ((uint32) 1 << 16); + ret = nm_write_reg(NMI_INTR_ENABLE, reg); + if (M2M_SUCCESS != ret) goto ERR1; +ERR1: + return ret; +} + +sint8 cpu_start(void) { + uint32 reg = 0; + sint8 ret; + + /** + reset regs + */ + ret = nm_write_reg(BOOTROM_REG,0); + ret += nm_write_reg(NMI_STATE_REG,0); + ret += nm_write_reg(NMI_REV_REG,0); + /** + Go... + **/ + ret += nm_read_reg_with_ret(0x1118, ®); + reg |= (1 << 0); + ret += nm_write_reg(0x1118, reg); + ret += nm_read_reg_with_ret(NMI_GLB_RESET_0, ®); + if ((reg & (1ul << 10)) == (1ul << 10)) { + reg &= ~(1ul << 10); + ret += nm_write_reg(NMI_GLB_RESET_0, reg); + } + reg |= (1ul << 10); + ret += nm_write_reg(NMI_GLB_RESET_0, reg); + nm_bsp_sleep(1); + return ret; +} + +uint32 nmi_get_chipid(void) +{ + static uint32 chipid = 0; + + if (chipid == 0) { + uint32 rfrevid; + + if((nm_read_reg_with_ret(0x1000, &chipid)) != M2M_SUCCESS) { + chipid = 0; + return 0; + } + //if((ret = nm_read_reg_with_ret(0x11fc, &revid)) != M2M_SUCCESS) { + // return 0; + //} + if((nm_read_reg_with_ret(0x13f4, &rfrevid)) != M2M_SUCCESS) { + chipid = 0; + return 0; + } + + if (chipid == 0x1002a0) { + if (rfrevid == 0x1) { /* 1002A0 */ + } else /* if (rfrevid == 0x2) */ { /* 1002A1 */ + chipid = 0x1002a1; + } + } else if(chipid == 0x1002b0) { + if(rfrevid == 3) { /* 1002B0 */ + } else if(rfrevid == 4) { /* 1002B1 */ + chipid = 0x1002b1; + } else /* if(rfrevid == 5) */ { /* 1002B2 */ + chipid = 0x1002b2; + } + }else if(chipid == 0x1000F0) { + if((nm_read_reg_with_ret(0x3B0000, &chipid)) != M2M_SUCCESS) { + chipid = 0; + return 0; + } + }else { + + } +//#define PROBE_FLASH +#ifdef PROBE_FLASH + if(chipid) { + UWORD32 flashid; + + flashid = probe_spi_flash(); + if(flashid == 0x1230ef) { + chipid &= ~(0x0f0000); + chipid |= 0x050000; + } + if(flashid == 0xc21320c2) { + chipid &= ~(0x0f0000); + chipid |= 0x050000; + } + } +#else + /*M2M is by default have SPI flash*/ + chipid &= ~(0x0f0000); + chipid |= 0x050000; +#endif /* PROBE_FLASH */ + } + return chipid; +} + +uint32 nmi_get_rfrevid(void) +{ + uint32 rfrevid; + if((nm_read_reg_with_ret(0x13f4, &rfrevid)) != M2M_SUCCESS) { + rfrevid = 0; + return 0; + } + return rfrevid; +} + +void restore_pmu_settings_after_global_reset(void) +{ + /* + * Must restore PMU register value after + * global reset if PMU toggle is done at + * least once since the last hard reset. + */ + if(REV(nmi_get_chipid()) >= REV_2B0) { + nm_write_reg(0x1e48, 0xb78469ce); + } +} + +void nmi_update_pll(void) +{ + uint32 pll; + + pll = nm_read_reg(0x1428); + pll &= ~0x1ul; + nm_write_reg(0x1428, pll); + pll |= 0x1ul; + nm_write_reg(0x1428, pll); + +} +void nmi_set_sys_clk_src_to_xo(void) +{ + uint32 val32; + + /* Switch system clock source to XO. This will take effect after nmi_update_pll(). */ + val32 = nm_read_reg(0x141c); + val32 |= (1 << 2); + nm_write_reg(0x141c, val32); + + /* Do PLL update */ + nmi_update_pll(); +} +sint8 chip_sleep(void) +{ + uint32 reg; + sint8 ret = M2M_SUCCESS; + + while(1) + { + ret = nm_read_reg_with_ret(CORT_HOST_COMM,®); + if(ret != M2M_SUCCESS) goto ERR1; + if((reg & NBIT0) == 0) break; + } + + /* Clear bit 1 */ + ret = nm_read_reg_with_ret(WAKE_CLK_REG, ®); + if(ret != M2M_SUCCESS)goto ERR1; + if(reg & NBIT1) + { + reg &=~NBIT1; + ret = nm_write_reg(WAKE_CLK_REG, reg); + if(ret != M2M_SUCCESS)goto ERR1; + } + + ret = nm_read_reg_with_ret(HOST_CORT_COMM, ®); + if(ret != M2M_SUCCESS)goto ERR1; + if(reg & NBIT0) + { + reg &= ~NBIT0; + ret = nm_write_reg(HOST_CORT_COMM, reg); + if(ret != M2M_SUCCESS)goto ERR1; + } + +ERR1: + return ret; +} +sint8 chip_wake(void) +{ + sint8 ret = M2M_SUCCESS; + uint32 reg = 0, clk_status_reg = 0,trials = 0; + + ret = nm_read_reg_with_ret(HOST_CORT_COMM, ®); + if(ret != M2M_SUCCESS)goto _WAKE_EXIT; + + if(!(reg & NBIT0)) + { + /*USE bit 0 to indicate host wakeup*/ + ret = nm_write_reg(HOST_CORT_COMM, reg|NBIT0); + if(ret != M2M_SUCCESS)goto _WAKE_EXIT; + } + + ret = nm_read_reg_with_ret(WAKE_CLK_REG, ®); + if(ret != M2M_SUCCESS)goto _WAKE_EXIT; + /* Set bit 1 */ + if(!(reg & NBIT1)) + { + ret = nm_write_reg(WAKE_CLK_REG, reg | NBIT1); + if(ret != M2M_SUCCESS) goto _WAKE_EXIT; + } + + do + { + ret = nm_read_reg_with_ret(CLOCKS_EN_REG, &clk_status_reg); + if(ret != M2M_SUCCESS) { + M2M_ERR("Bus error (5).%d %lx\n",ret,clk_status_reg); + goto _WAKE_EXIT; + } + if(clk_status_reg & NBIT2) { + break; + } + nm_bsp_sleep(2); + trials++; + if(trials > WAKUP_TRAILS_TIMEOUT) + { + M2M_ERR("Failed to wakup the chip\n"); + ret = M2M_ERR_TIME_OUT; + goto _WAKE_EXIT; + } + }while(1); + + /*workaround sometimes spi fail to read clock regs after reading/writing clockless registers*/ + nm_bus_reset(); + +_WAKE_EXIT: + return ret; +} +sint8 cpu_halt(void) +{ + sint8 ret; + uint32 reg = 0; + ret = nm_read_reg_with_ret(0x1118, ®); + reg |= (1 << 0); + ret += nm_write_reg(0x1118, reg); + ret += nm_read_reg_with_ret(NMI_GLB_RESET_0, ®); + if ((reg & (1ul << 10)) == (1ul << 10)) { + reg &= ~(1ul << 10); + ret += nm_write_reg(NMI_GLB_RESET_0, reg); + ret += nm_read_reg_with_ret(NMI_GLB_RESET_0, ®); + } + return ret; +} +sint8 chip_reset_and_cpu_halt(void) +{ + sint8 ret = M2M_SUCCESS; + + /*Wakeup needed only for I2C interface*/ + ret = chip_wake(); + if(ret != M2M_SUCCESS) goto ERR1; + /*Reset and CPU halt need for no wait board only*/ + ret = chip_reset(); + if(ret != M2M_SUCCESS) goto ERR1; + ret = cpu_halt(); + if(ret != M2M_SUCCESS) goto ERR1; +ERR1: + return ret; +} +sint8 chip_reset(void) +{ + sint8 ret = M2M_SUCCESS; + ret = nm_write_reg(NMI_GLB_RESET_0, 0); + nm_bsp_sleep(50); + return ret; +} + +sint8 wait_for_bootrom(uint8 arg) +{ + sint8 ret = M2M_SUCCESS; + uint32 reg = 0, cnt = 0; + uint32 u32GpReg1 = 0; + uint32 u32DriverVerInfo = M2M_MAKE_VERSION_INFO(M2M_RELEASE_VERSION_MAJOR_NO,\ + M2M_RELEASE_VERSION_MINOR_NO, M2M_RELEASE_VERSION_PATCH_NO,\ + M2M_RELEASE_VERSION_MAJOR_NO, M2M_RELEASE_VERSION_MINOR_NO,\ + M2M_RELEASE_VERSION_PATCH_NO); + + + reg = 0; + while(1) { + reg = nm_read_reg(0x1014); /* wait for efuse loading done */ + if (reg & 0x80000000) { + break; + } + nm_bsp_sleep(1); /* TODO: Why bus error if this delay is not here. */ + } + reg = nm_read_reg(M2M_WAIT_FOR_HOST_REG); + reg &= 0x1; + + /* check if waiting for the host will be skipped or not */ + if(reg == 0) + { + reg = 0; + while(reg != M2M_FINISH_BOOT_ROM) + { + nm_bsp_sleep(1); + reg = nm_read_reg(BOOTROM_REG); + + if(++cnt > TIMEOUT) + { + M2M_DBG("failed to load firmware from flash.\n"); + ret = M2M_ERR_INIT; + goto ERR2; + } + } + } + + if(M2M_WIFI_MODE_ATE_HIGH == arg) { + nm_write_reg(NMI_REV_REG, M2M_ATE_FW_START_VALUE); + nm_write_reg(NMI_STATE_REG, NBIT20); + }else if(M2M_WIFI_MODE_ATE_LOW == arg) { + nm_write_reg(NMI_REV_REG, M2M_ATE_FW_START_VALUE); + nm_write_reg(NMI_STATE_REG, 0); + }else if(M2M_WIFI_MODE_ETHERNET == arg){ + u32GpReg1 = rHAVE_ETHERNET_MODE_BIT; + nm_write_reg(NMI_STATE_REG, u32DriverVerInfo); + } else { + /*bypass this step*/ + nm_write_reg(NMI_STATE_REG, u32DriverVerInfo); + } + + if(REV(nmi_get_chipid()) >= REV_3A0){ + chip_apply_conf(u32GpReg1 | rHAVE_USE_PMU_BIT); + } else { + chip_apply_conf(u32GpReg1); + } + M2M_INFO("DriverVerInfo: 0x%08lx\n",u32DriverVerInfo); + + nm_write_reg(BOOTROM_REG,M2M_START_FIRMWARE); + +#ifdef __ROM_TEST__ + rom_test(); +#endif /* __ROM_TEST__ */ + +ERR2: + return ret; +} + +sint8 wait_for_firmware_start(uint8 arg) +{ + sint8 ret = M2M_SUCCESS; + uint32 reg = 0, cnt = 0; + uint32 u32Timeout = TIMEOUT; + volatile uint32 regAddress = NMI_STATE_REG; + volatile uint32 checkValue = M2M_FINISH_INIT_STATE; + + if((M2M_WIFI_MODE_ATE_HIGH == arg)||(M2M_WIFI_MODE_ATE_LOW == arg)) { + regAddress = NMI_REV_REG; + checkValue = M2M_ATE_FW_IS_UP_VALUE; + } else { + /*bypass this step*/ + } + + + while (checkValue != reg) + { + nm_bsp_sleep(2); /* TODO: Why bus error if this delay is not here. */ + M2M_DBG("%x %x %x\n",(unsigned int)nm_read_reg(0x108c),(unsigned int)nm_read_reg(0x108c),(unsigned int)nm_read_reg(0x14A0)); + reg = nm_read_reg(regAddress); + if(++cnt >= u32Timeout) + { + M2M_DBG("Time out for wait firmware Run\n"); + ret = M2M_ERR_INIT; + goto ERR; + } + } + if(M2M_FINISH_INIT_STATE == checkValue) + { + nm_write_reg(NMI_STATE_REG, 0); + } +ERR: + return ret; +} + +sint8 chip_deinit(void) +{ + uint32 reg = 0; + sint8 ret; + + /** + stop the firmware, need a re-download + **/ + ret = nm_read_reg_with_ret(NMI_GLB_RESET_0, ®); + if (ret != M2M_SUCCESS) { + M2M_ERR("failed to de-initialize\n"); + goto ERR1; + } + reg &= ~(1 << 10); + ret = nm_write_reg(NMI_GLB_RESET_0, reg); + if (ret != M2M_SUCCESS) { + M2M_ERR("failed to de-initialize\n"); + goto ERR1; + } + +ERR1: + return ret; +} + +#ifdef CONF_PERIPH + +sint8 set_gpio_dir(uint8 gpio, uint8 dir) +{ + uint32 val32; + sint8 ret; + + ret = nm_read_reg_with_ret(0x20108, &val32); + if(ret != M2M_SUCCESS) goto _EXIT; + + if(dir) { + val32 |= (1ul << gpio); + } else { + val32 &= ~(1ul << gpio); + } + + ret = nm_write_reg(0x20108, val32); + +_EXIT: + return ret; +} +sint8 set_gpio_val(uint8 gpio, uint8 val) +{ + uint32 val32; + sint8 ret; + + ret = nm_read_reg_with_ret(0x20100, &val32); + if(ret != M2M_SUCCESS) goto _EXIT; + + if(val) { + val32 |= (1ul << gpio); + } else { + val32 &= ~(1ul << gpio); + } + + ret = nm_write_reg(0x20100, val32); + +_EXIT: + return ret; +} + +sint8 get_gpio_val(uint8 gpio, uint8* val) +{ + uint32 val32; + sint8 ret; + + ret = nm_read_reg_with_ret(0x20104, &val32); + if(ret != M2M_SUCCESS) goto _EXIT; + + *val = (uint8)((val32 >> gpio) & 0x01); + +_EXIT: + return ret; +} + +sint8 pullup_ctrl(uint32 pinmask, uint8 enable) +{ + sint8 s8Ret; + uint32 val32; + s8Ret = nm_read_reg_with_ret(0x142c, &val32); + if(s8Ret != M2M_SUCCESS) { + M2M_ERR("[pullup_ctrl]: failed to read\n"); + goto _EXIT; + } + if(enable) { + val32 &= ~pinmask; + } else { + val32 |= pinmask; + } + s8Ret = nm_write_reg(0x142c, val32); + if(s8Ret != M2M_SUCCESS) { + M2M_ERR("[pullup_ctrl]: failed to write\n"); + goto _EXIT; + } +_EXIT: + return s8Ret; +} +#endif /* CONF_PERIPH */ + +sint8 nmi_get_otp_mac_address(uint8 *pu8MacAddr, uint8 * pu8IsValid) +{ + sint8 ret; + uint32 u32RegValue; + uint8 mac[6]; + tstrGpRegs strgp = {0}; + + ret = nm_read_reg_with_ret(rNMI_GP_REG_2, &u32RegValue); + if(ret != M2M_SUCCESS) goto _EXIT_ERR; + + ret = nm_read_block(u32RegValue|0x30000,(uint8*)&strgp,sizeof(tstrGpRegs)); + if(ret != M2M_SUCCESS) goto _EXIT_ERR; + u32RegValue = strgp.u32Mac_efuse_mib; + + if(!EFUSED_MAC(u32RegValue)) { + M2M_DBG("Default MAC\n"); + m2m_memset(pu8MacAddr, 0, 6); + goto _EXIT_ERR; + } + + M2M_DBG("OTP MAC\n"); + u32RegValue >>=16; + ret = nm_read_block(u32RegValue|0x30000, mac, 6); + m2m_memcpy(pu8MacAddr,mac,6); + if(pu8IsValid) *pu8IsValid = 1; + return ret; + +_EXIT_ERR: + if(pu8IsValid) *pu8IsValid = 0; + return ret; +} + +sint8 nmi_get_mac_address(uint8 *pu8MacAddr) +{ + sint8 ret; + uint32 u32RegValue; + uint8 mac[6]; + tstrGpRegs strgp = {0}; + + ret = nm_read_reg_with_ret(rNMI_GP_REG_2, &u32RegValue); + if(ret != M2M_SUCCESS) goto _EXIT_ERR; + + ret = nm_read_block(u32RegValue|0x30000,(uint8*)&strgp,sizeof(tstrGpRegs)); + if(ret != M2M_SUCCESS) goto _EXIT_ERR; + u32RegValue = strgp.u32Mac_efuse_mib; + + u32RegValue &=0x0000ffff; + ret = nm_read_block(u32RegValue|0x30000, mac, 6); + m2m_memcpy(pu8MacAddr, mac, 6); + + return ret; + +_EXIT_ERR: + return ret; +} diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmasic.h b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmasic.h new file mode 100644 index 0000000000000..84a395b8fac7f --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmasic.h @@ -0,0 +1,215 @@ +/** + * + * \file + * + * \brief This module contains NMC1500 ASIC specific internal APIs. + * + * Copyright (c) 2016-2017 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ +#ifndef _NMASIC_H_ +#define _NMASIC_H_ + +#include "common/include/nm_common.h" + +#define NMI_PERIPH_REG_BASE 0x1000 +#define NMI_CHIPID (NMI_PERIPH_REG_BASE) +#define rNMI_GP_REG_0 (0x149c) +#define rNMI_GP_REG_1 (0x14A0) +#define rNMI_GP_REG_2 (0xc0008) +#define rNMI_GLB_RESET (0x1400) +#define rNMI_BOOT_RESET_MUX (0x1118) +#define NMI_STATE_REG (0x108c) +#define BOOTROM_REG (0xc000c) +#define NMI_REV_REG (0x207ac) /*Also, Used to load ATE firmware from SPI Flash and to ensure that it is running too*/ +#define NMI_REV_REG_ATE (0x1048) /*Revision info register in case of ATE FW*/ +#define M2M_WAIT_FOR_HOST_REG (0x207bc) +#define M2M_FINISH_INIT_STATE 0x02532636UL +#define M2M_FINISH_BOOT_ROM 0x10add09eUL +#define M2M_START_FIRMWARE 0xef522f61UL +#define M2M_START_PS_FIRMWARE 0x94992610UL + +#define M2M_ATE_FW_START_VALUE (0x3C1CD57D) /*Also, Change this value in boot_firmware if it will be changed here*/ +#define M2M_ATE_FW_IS_UP_VALUE (0xD75DC1C3) /*Also, Change this value in ATE (Burst) firmware if it will be changed here*/ + +#define REV_2B0 (0x2B0) +#define REV_B0 (0x2B0) +#define REV_3A0 (0x3A0) +#define GET_CHIPID() nmi_get_chipid() +#define ISNMC1000(id) ((((id) & 0xfffff000) == 0x100000) ? 1 : 0) +#define ISNMC1500(id) ((((id) & 0xfffff000) == 0x150000) ? 1 : 0) +#define ISNMC3000(id) ((((id) & 0xfff00000) == 0x300000) ? 1 : 0) +#define REV(id) (((id) & 0x00000fff )) +#define EFUSED_MAC(value) (value & 0xffff0000) + +#define rHAVE_SDIO_IRQ_GPIO_BIT (NBIT0) +#define rHAVE_USE_PMU_BIT (NBIT1) +#define rHAVE_SLEEP_CLK_SRC_RTC_BIT (NBIT2) +#define rHAVE_SLEEP_CLK_SRC_XO_BIT (NBIT3) +#define rHAVE_EXT_PA_INV_TX_RX (NBIT4) +#define rHAVE_LEGACY_RF_SETTINGS (NBIT5) +#define rHAVE_LOGS_DISABLED_BIT (NBIT6) +#define rHAVE_ETHERNET_MODE_BIT (NBIT7) +#define rHAVE_RESERVED1_BIT (NBIT8) + +typedef struct{ + uint32 u32Mac_efuse_mib; + uint32 u32Firmware_Ota_rev; +}tstrGpRegs; + +#ifdef __cplusplus + extern "C" { +#endif + +/* +* @fn cpu_halt +* @brief +*/ +sint8 cpu_halt(void); +/* +* @fn chip_sleep +* @brief +*/ +sint8 chip_sleep(void); +/* +* @fn chip_wake +* @brief +*/ +sint8 chip_wake(void); +/* +* @fn chip_idle +* @brief +*/ +void chip_idle(void); +/* +* @fn enable_interrupts +* @brief +*/ +sint8 enable_interrupts(void); +/* +* @fn cpu_start +* @brief +*/ +sint8 cpu_start(void); +/* +* @fn nmi_get_chipid +* @brief +*/ +uint32 nmi_get_chipid(void); +/* +* @fn nmi_get_rfrevid +* @brief +*/ +uint32 nmi_get_rfrevid(void); +/* +* @fn restore_pmu_settings_after_global_reset +* @brief +*/ +void restore_pmu_settings_after_global_reset(void); +/* +* @fn nmi_update_pll +* @brief +*/ +void nmi_update_pll(void); +/* +* @fn nmi_set_sys_clk_src_to_xo +* @brief +*/ +void nmi_set_sys_clk_src_to_xo(void); +/* +* @fn chip_reset +* @brief +*/ +sint8 chip_reset(void); +/* +* @fn wait_for_bootrom +* @brief +*/ +sint8 wait_for_bootrom(uint8); +/* +* @fn wait_for_firmware_start +* @brief +*/ +sint8 wait_for_firmware_start(uint8); +/* +* @fn chip_deinit +* @brief +*/ +sint8 chip_deinit(void); +/* +* @fn chip_reset_and_cpu_halt +* @brief +*/ +sint8 chip_reset_and_cpu_halt(void); +/* +* @fn set_gpio_dir +* @brief +*/ +sint8 set_gpio_dir(uint8 gpio, uint8 dir); +/* +* @fn set_gpio_val +* @brief +*/ +sint8 set_gpio_val(uint8 gpio, uint8 val); +/* +* @fn get_gpio_val +* @brief +*/ +sint8 get_gpio_val(uint8 gpio, uint8* val); +/* +* @fn pullup_ctrl +* @brief +*/ +sint8 pullup_ctrl(uint32 pinmask, uint8 enable); +/* +* @fn nmi_get_otp_mac_address +* @brief +*/ +sint8 nmi_get_otp_mac_address(uint8 *pu8MacAddr, uint8 * pu8IsValid); +/* +* @fn nmi_get_mac_address +* @brief +*/ +sint8 nmi_get_mac_address(uint8 *pu8MacAddr); +/* +* @fn chip_apply_conf +* @brief +*/ +sint8 chip_apply_conf(uint32 u32conf); + +#ifdef __cplusplus + } +#endif + +#endif /*_NMASIC_H_*/ diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmbus.c b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmbus.c new file mode 100644 index 0000000000000..1ae1d1e783899 --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmbus.c @@ -0,0 +1,298 @@ +/** + * + * \file + * + * \brief This module contains NMC1000 bus APIs implementation. + * + * Copyright (c) 2016-2017 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ +#ifndef CORTUS_APP + +#include "nmbus.h" +#include "nmi2c.h" +#include "nmspi.h" +#include "nmuart.h" + +#define MAX_TRX_CFG_SZ 8 + +/** +* @fn nm_bus_iface_init +* @brief Initialize bus interface +* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure +* @author M. Abdelmawla +* @date 11 July 2012 +* @version 1.0 +*/ +sint8 nm_bus_iface_init(void *pvInitVal) +{ + sint8 ret = M2M_SUCCESS; + ret = nm_bus_init(pvInitVal); + return ret; +} + +/** +* @fn nm_bus_iface_deinit +* @brief Deinitialize bus interface +* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure +* @author Samer Sarhan +* @date 07 April 2014 +* @version 1.0 +*/ +sint8 nm_bus_iface_deinit(void) +{ + sint8 ret = M2M_SUCCESS; + ret = nm_bus_deinit(); + + return ret; +} + +/** +* @fn nm_bus_reset +* @brief reset bus interface +* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure +* @version 1.0 +*/ +sint8 nm_bus_reset(void) +{ + sint8 ret = M2M_SUCCESS; +#ifdef CONF_WINC_USE_UART +#elif defined (CONF_WINC_USE_SPI) + return nm_spi_reset(); +#elif defined (CONF_WINC_USE_I2C) +#else +#error "Plesae define bus usage" +#endif + + return ret; +} + +/** +* @fn nm_bus_iface_reconfigure +* @brief reconfigure bus interface +* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure +* @author Viswanathan Murugesan +* @date 22 Oct 2014 +* @version 1.0 +*/ +sint8 nm_bus_iface_reconfigure(void *ptr) +{ + sint8 ret = M2M_SUCCESS; +#ifdef CONF_WINC_USE_UART + ret = nm_uart_reconfigure(ptr); +#endif + return ret; +} +/* +* @fn nm_read_reg +* @brief Read register +* @param [in] u32Addr +* Register address +* @return Register value +* @author M. Abdelmawla +* @date 11 July 2012 +* @version 1.0 +*/ +uint32 nm_read_reg(uint32 u32Addr) +{ +#ifdef CONF_WINC_USE_UART + return nm_uart_read_reg(u32Addr); +#elif defined (CONF_WINC_USE_SPI) + return nm_spi_read_reg(u32Addr); +#elif defined (CONF_WINC_USE_I2C) + return nm_i2c_read_reg(u32Addr); +#else +#error "Plesae define bus usage" +#endif + +} + +/* +* @fn nm_read_reg_with_ret +* @brief Read register with error code return +* @param [in] u32Addr +* Register address +* @param [out] pu32RetVal +* Pointer to u32 variable used to return the read value +* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure +* @author M. Abdelmawla +* @date 11 July 2012 +* @version 1.0 +*/ +sint8 nm_read_reg_with_ret(uint32 u32Addr, uint32* pu32RetVal) +{ +#ifdef CONF_WINC_USE_UART + return nm_uart_read_reg_with_ret(u32Addr,pu32RetVal); +#elif defined (CONF_WINC_USE_SPI) + return nm_spi_read_reg_with_ret(u32Addr,pu32RetVal); +#elif defined (CONF_WINC_USE_I2C) + return nm_i2c_read_reg_with_ret(u32Addr,pu32RetVal); +#else +#error "Plesae define bus usage" +#endif +} + +/* +* @fn nm_write_reg +* @brief write register +* @param [in] u32Addr +* Register address +* @param [in] u32Val +* Value to be written to the register +* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure +* @author M. Abdelmawla +* @date 11 July 2012 +* @version 1.0 +*/ +sint8 nm_write_reg(uint32 u32Addr, uint32 u32Val) +{ +#ifdef CONF_WINC_USE_UART + return nm_uart_write_reg(u32Addr,u32Val); +#elif defined (CONF_WINC_USE_SPI) + return nm_spi_write_reg(u32Addr,u32Val); +#elif defined (CONF_WINC_USE_I2C) + return nm_i2c_write_reg(u32Addr,u32Val); +#else +#error "Plesae define bus usage" +#endif +} + +static sint8 p_nm_read_block(uint32 u32Addr, uint8 *puBuf, uint16 u16Sz) +{ +#ifdef CONF_WINC_USE_UART + return nm_uart_read_block(u32Addr,puBuf,u16Sz); +#elif defined (CONF_WINC_USE_SPI) + return nm_spi_read_block(u32Addr,puBuf,u16Sz); +#elif defined (CONF_WINC_USE_I2C) + return nm_i2c_read_block(u32Addr,puBuf,u16Sz); +#else +#error "Plesae define bus usage" +#endif + +} +/* +* @fn nm_read_block +* @brief Read block of data +* @param [in] u32Addr +* Start address +* @param [out] puBuf +* Pointer to a buffer used to return the read data +* @param [in] u32Sz +* Number of bytes to read. The buffer size must be >= u32Sz +* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure +* @author M. Abdelmawla +* @date 11 July 2012 +* @version 1.0 +*/ +sint8 nm_read_block(uint32 u32Addr, uint8 *puBuf, uint32 u32Sz) +{ + uint16 u16MaxTrxSz = egstrNmBusCapabilities.u16MaxTrxSz - MAX_TRX_CFG_SZ; + uint32 off = 0; + sint8 s8Ret = M2M_SUCCESS; + + for(;;) + { + if(u32Sz <= u16MaxTrxSz) + { + s8Ret += p_nm_read_block(u32Addr, &puBuf[off], (uint16)u32Sz); + break; + } + else + { + s8Ret += p_nm_read_block(u32Addr, &puBuf[off], u16MaxTrxSz); + if(M2M_SUCCESS != s8Ret) break; + u32Sz -= u16MaxTrxSz; + off += u16MaxTrxSz; + u32Addr += u16MaxTrxSz; + } + } + + return s8Ret; +} + +static sint8 p_nm_write_block(uint32 u32Addr, uint8 *puBuf, uint16 u16Sz) +{ +#ifdef CONF_WINC_USE_UART + return nm_uart_write_block(u32Addr,puBuf,u16Sz); +#elif defined (CONF_WINC_USE_SPI) + return nm_spi_write_block(u32Addr,puBuf,u16Sz); +#elif defined (CONF_WINC_USE_I2C) + return nm_i2c_write_block(u32Addr,puBuf,u16Sz); +#else +#error "Plesae define bus usage" +#endif + +} +/** +* @fn nm_write_block +* @brief Write block of data +* @param [in] u32Addr +* Start address +* @param [in] puBuf +* Pointer to the buffer holding the data to be written +* @param [in] u32Sz +* Number of bytes to write. The buffer size must be >= u32Sz +* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure +* @author M. Abdelmawla +* @date 11 July 2012 +* @version 1.0 +*/ +sint8 nm_write_block(uint32 u32Addr, uint8 *puBuf, uint32 u32Sz) +{ + uint16 u16MaxTrxSz = egstrNmBusCapabilities.u16MaxTrxSz - MAX_TRX_CFG_SZ; + uint32 off = 0; + sint8 s8Ret = M2M_SUCCESS; + + for(;;) + { + if(u32Sz <= u16MaxTrxSz) + { + s8Ret += p_nm_write_block(u32Addr, &puBuf[off], (uint16)u32Sz); + break; + } + else + { + s8Ret += p_nm_write_block(u32Addr, &puBuf[off], u16MaxTrxSz); + if(M2M_SUCCESS != s8Ret) break; + u32Sz -= u16MaxTrxSz; + off += u16MaxTrxSz; + u32Addr += u16MaxTrxSz; + } + } + + return s8Ret; +} + +#endif + diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmbus.h b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmbus.h new file mode 100644 index 0000000000000..2ea7838b1a33d --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmbus.h @@ -0,0 +1,147 @@ +/** + * + * \file + * + * \brief This module contains NMC1000 bus APIs implementation. + * + * Copyright (c) 2016-2017 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + +#ifndef _NMBUS_H_ +#define _NMBUS_H_ + +#include "common/include/nm_common.h" +#include "bus_wrapper/include/nm_bus_wrapper.h" + + + +#ifdef __cplusplus +extern "C"{ +#endif +/** +* @fn nm_bus_iface_init +* @brief Initialize bus interface +* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure +*/ +sint8 nm_bus_iface_init(void *); + + +/** +* @fn nm_bus_iface_deinit +* @brief Deinitialize bus interface +* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure +*/ +sint8 nm_bus_iface_deinit(void); + +/** +* @fn nm_bus_reset +* @brief reset bus interface +* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure +* @version 1.0 +*/ +sint8 nm_bus_reset(void); + +/** +* @fn nm_bus_iface_reconfigure +* @brief reconfigure bus interface +* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure +*/ +sint8 nm_bus_iface_reconfigure(void *ptr); + +/** +* @fn nm_read_reg +* @brief Read register +* @param [in] u32Addr +* Register address +* @return Register value +*/ +uint32 nm_read_reg(uint32 u32Addr); + +/** +* @fn nm_read_reg_with_ret +* @brief Read register with error code return +* @param [in] u32Addr +* Register address +* @param [out] pu32RetVal +* Pointer to u32 variable used to return the read value +* @return ZERO in case of success and M2M_ERR_BUS_FAIL in case of failure +*/ +sint8 nm_read_reg_with_ret(uint32 u32Addr, uint32* pu32RetVal); + +/** +* @fn nm_write_reg +* @brief write register +* @param [in] u32Addr +* Register address +* @param [in] u32Val +* Value to be written to the register +* @return ZERO in case of success and M2M_ERR_BUS_FAIL in case of failure +*/ +sint8 nm_write_reg(uint32 u32Addr, uint32 u32Val); + +/** +* @fn nm_read_block +* @brief Read block of data +* @param [in] u32Addr +* Start address +* @param [out] puBuf +* Pointer to a buffer used to return the read data +* @param [in] u32Sz +* Number of bytes to read. The buffer size must be >= u32Sz +* @return ZERO in case of success and M2M_ERR_BUS_FAIL in case of failure +*/ +sint8 nm_read_block(uint32 u32Addr, uint8 *puBuf, uint32 u32Sz); + +/** +* @fn nm_write_block +* @brief Write block of data +* @param [in] u32Addr +* Start address +* @param [in] puBuf +* Pointer to the buffer holding the data to be written +* @param [in] u32Sz +* Number of bytes to write. The buffer size must be >= u32Sz +* @return ZERO in case of success and M2M_ERR_BUS_FAIL in case of failure +*/ +sint8 nm_write_block(uint32 u32Addr, uint8 *puBuf, uint32 u32Sz); + + + + +#ifdef __cplusplus +} +#endif + +#endif /* _NMBUS_H_ */ diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmdrv.c b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmdrv.c new file mode 100644 index 0000000000000..d0b20439f9235 --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmdrv.c @@ -0,0 +1,389 @@ +/** + * + * \file + * + * \brief This module contains NMC1000 M2M driver APIs implementation. + * + * Copyright (c) 2016-2017 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + +#include "common/include/nm_common.h" +#include "driver/source/nmbus.h" +#include "bsp/include/nm_bsp.h" +#include "driver/source/nmdrv.h" +#include "driver/source/nmasic.h" +#include "driver/include/m2m_types.h" +#include "spi_flash/include/spi_flash.h" + +#ifdef CONF_WINC_USE_SPI +#include "driver/source/nmspi.h" +#endif + +/** +* @fn nm_get_firmware_info(tstrM2mRev* M2mRev) +* @brief Get Firmware version info +* @param [out] M2mRev +* pointer holds address of structure "tstrM2mRev" that contains the firmware version parameters +* @version 1.0 +*/ +sint8 nm_get_firmware_info(tstrM2mRev* M2mRev) +{ + uint16 curr_drv_ver, min_req_drv_ver,curr_firm_ver; + uint32 reg = 0; + sint8 ret = M2M_SUCCESS; + + ret = nm_read_reg_with_ret(NMI_REV_REG, ®); + //In case the Firmware running is ATE fw + if(M2M_ATE_FW_IS_UP_VALUE == reg) + { + //Read FW info again from the register specified for ATE + ret = nm_read_reg_with_ret(NMI_REV_REG_ATE, ®); + } + M2mRev->u8DriverMajor = M2M_GET_DRV_MAJOR(reg); + M2mRev->u8DriverMinor = M2M_GET_DRV_MINOR(reg); + M2mRev->u8DriverPatch = M2M_GET_DRV_PATCH(reg); + M2mRev->u8FirmwareMajor = M2M_GET_FW_MAJOR(reg); + M2mRev->u8FirmwareMinor = M2M_GET_FW_MINOR(reg); + M2mRev->u8FirmwarePatch = M2M_GET_FW_PATCH(reg); + M2mRev->u32Chipid = nmi_get_chipid(); + M2mRev->u16FirmwareSvnNum = 0; + + curr_firm_ver = M2M_MAKE_VERSION(M2mRev->u8FirmwareMajor, M2mRev->u8FirmwareMinor,M2mRev->u8FirmwarePatch); + curr_drv_ver = M2M_MAKE_VERSION(M2M_RELEASE_VERSION_MAJOR_NO, M2M_RELEASE_VERSION_MINOR_NO, M2M_RELEASE_VERSION_PATCH_NO); + min_req_drv_ver = M2M_MAKE_VERSION(M2mRev->u8DriverMajor, M2mRev->u8DriverMinor,M2mRev->u8DriverPatch); + if(curr_drv_ver < min_req_drv_ver) { + /*The current driver version should be larger or equal + than the min driver that the current firmware support */ + ret = M2M_ERR_FW_VER_MISMATCH; + } + if(curr_drv_ver > curr_firm_ver) { + /*The current driver should be equal or less than the firmware version*/ + ret = M2M_ERR_FW_VER_MISMATCH; + } + return ret; +} +/** +* @fn nm_get_firmware_info(tstrM2mRev* M2mRev) +* @brief Get Firmware version info +* @param [out] M2mRev +* pointer holds address of structure "tstrM2mRev" that contains the firmware version parameters +* @version 1.0 +*/ +sint8 nm_get_firmware_full_info(tstrM2mRev* pstrRev) +{ + uint16 curr_drv_ver, min_req_drv_ver,curr_firm_ver; + uint32 reg = 0; + sint8 ret = M2M_SUCCESS; + tstrGpRegs strgp = {0}; + if (pstrRev != NULL) + { + m2m_memset((uint8*)pstrRev,0,sizeof(tstrM2mRev)); + ret = nm_read_reg_with_ret(rNMI_GP_REG_2, ®); + if(ret == M2M_SUCCESS) + { + if(reg != 0) + { + ret = nm_read_block(reg|0x30000,(uint8*)&strgp,sizeof(tstrGpRegs)); + if(ret == M2M_SUCCESS) + { + reg = strgp.u32Firmware_Ota_rev; + reg &= 0x0000ffff; + if(reg != 0) + { + ret = nm_read_block(reg|0x30000,(uint8*)pstrRev,sizeof(tstrM2mRev)); + if(ret == M2M_SUCCESS) + { + curr_firm_ver = M2M_MAKE_VERSION(pstrRev->u8FirmwareMajor, pstrRev->u8FirmwareMinor,pstrRev->u8FirmwarePatch); + curr_drv_ver = M2M_MAKE_VERSION(M2M_RELEASE_VERSION_MAJOR_NO, M2M_RELEASE_VERSION_MINOR_NO, M2M_RELEASE_VERSION_PATCH_NO); + min_req_drv_ver = M2M_MAKE_VERSION(pstrRev->u8DriverMajor, pstrRev->u8DriverMinor,pstrRev->u8DriverPatch); + if((curr_firm_ver == 0)||(min_req_drv_ver == 0)||(min_req_drv_ver == 0)){ + ret = M2M_ERR_FAIL; + goto EXIT; + } + if(curr_drv_ver < min_req_drv_ver) { + /*The current driver version should be larger or equal + than the min driver that the current firmware support */ + ret = M2M_ERR_FW_VER_MISMATCH; + goto EXIT; + } + if(curr_drv_ver > curr_firm_ver) { + /*The current driver should be equal or less than the firmware version*/ + ret = M2M_ERR_FW_VER_MISMATCH; + goto EXIT; + } + } + }else { + ret = M2M_ERR_FAIL; + } + } + }else{ + ret = M2M_ERR_FAIL; + } + } + } +EXIT: + return ret; +} +/** +* @fn nm_get_ota_firmware_info(tstrM2mRev* pstrRev) +* @brief Get Firmware version info +* @param [out] M2mRev +* pointer holds address of structure "tstrM2mRev" that contains the firmware version parameters + +* @version 1.0 +*/ +sint8 nm_get_ota_firmware_info(tstrM2mRev* pstrRev) +{ + uint16 curr_drv_ver, min_req_drv_ver,curr_firm_ver; + uint32 reg = 0; + sint8 ret; + tstrGpRegs strgp = {0}; + + if (pstrRev != NULL) + { + m2m_memset((uint8*)pstrRev,0,sizeof(tstrM2mRev)); + ret = nm_read_reg_with_ret(rNMI_GP_REG_2, ®); + if(ret == M2M_SUCCESS) + { + if(reg != 0) + { + ret = nm_read_block(reg|0x30000,(uint8*)&strgp,sizeof(tstrGpRegs)); + if(ret == M2M_SUCCESS) + { + reg = strgp.u32Firmware_Ota_rev; + reg >>= 16; + if(reg != 0) + { + ret = nm_read_block(reg|0x30000,(uint8*)pstrRev,sizeof(tstrM2mRev)); + if(ret == M2M_SUCCESS) + { + curr_firm_ver = M2M_MAKE_VERSION(pstrRev->u8FirmwareMajor, pstrRev->u8FirmwareMinor,pstrRev->u8FirmwarePatch); + curr_drv_ver = M2M_MAKE_VERSION(M2M_RELEASE_VERSION_MAJOR_NO, M2M_RELEASE_VERSION_MINOR_NO, M2M_RELEASE_VERSION_PATCH_NO); + min_req_drv_ver = M2M_MAKE_VERSION(pstrRev->u8DriverMajor, pstrRev->u8DriverMinor,pstrRev->u8DriverPatch); + if((curr_firm_ver == 0)||(min_req_drv_ver == 0)||(min_req_drv_ver == 0)){ + ret = M2M_ERR_FAIL; + goto EXIT; + } + if(curr_drv_ver < min_req_drv_ver) { + /*The current driver version should be larger or equal + than the min driver that the current firmware support */ + ret = M2M_ERR_FW_VER_MISMATCH; + } + if(curr_drv_ver > curr_firm_ver) { + /*The current driver should be equal or less than the firmware version*/ + ret = M2M_ERR_FW_VER_MISMATCH; + } + } + }else{ + ret = M2M_ERR_INVALID; + } + } + }else{ + ret = M2M_ERR_FAIL; + } + } + } else { + ret = M2M_ERR_INVALID_ARG; + } +EXIT: + return ret; +} + + + +/* +* @fn nm_drv_init_download_mode +* @brief Initialize NMC1000 driver +* @return M2M_SUCCESS in case of success and Negative error code in case of failure +* @param [in] arg +* Generic argument +* @author Viswanathan Murugesan +* @date 10 Oct 2014 +* @version 1.0 +*/ +sint8 nm_drv_init_download_mode() +{ + sint8 ret = M2M_SUCCESS; + + ret = nm_bus_iface_init(NULL); + if (M2M_SUCCESS != ret) { + M2M_ERR("[nmi start]: fail init bus\n"); + goto ERR1; + } + + /** + TODO:reset the chip and halt the cpu in case of no wait efuse is set (add the no wait effuse check) + */ + if(!ISNMC3000(GET_CHIPID())) + { + /*Execuate that function only for 1500A/B, no room in 3000, but it may be needed in 3400 no wait*/ + chip_reset_and_cpu_halt(); + } + +#ifdef CONF_WINC_USE_SPI + /* Must do this after global reset to set SPI data packet size. */ + nm_spi_init(); +#endif + + M2M_INFO("Chip ID %lx\n", nmi_get_chipid()); + + /*disable all interrupt in ROM (to disable uart) in 2b0 chip*/ + nm_write_reg(0x20300,0); + +ERR1: + return ret; +} + +/* +* @fn nm_drv_init +* @brief Initialize NMC1000 driver +* @return M2M_SUCCESS in case of success and Negative error code in case of failure +* @param [in] arg +* Generic argument +* @author M. Abdelmawla +* @date 15 July 2012 +* @version 1.0 +*/ +sint8 nm_drv_init(void * arg) +{ + sint8 ret = M2M_SUCCESS; + uint8 u8Mode; + + if(NULL != arg) { + u8Mode = *((uint8 *)arg); + if((u8Mode < M2M_WIFI_MODE_NORMAL)||(u8Mode >= M2M_WIFI_MODE_MAX)) { + u8Mode = M2M_WIFI_MODE_NORMAL; + } + } else { + u8Mode = M2M_WIFI_MODE_NORMAL; + } + + ret = nm_bus_iface_init(NULL); + if (M2M_SUCCESS != ret) { + M2M_ERR("[nmi start]: fail init bus\n"); + goto ERR1; + } + +#ifdef BUS_ONLY + return; +#endif + + +#ifdef NO_HW_CHIP_EN + ret = chip_wake(); + if (M2M_SUCCESS != ret) { + M2M_ERR("[nmi start]: fail chip_wakeup\n"); + goto ERR2; + } + /** + Go... + **/ + ret = chip_reset(); + if (M2M_SUCCESS != ret) { + goto ERR2; + } +#endif + M2M_INFO("Chip ID %lx\n", nmi_get_chipid()); +#ifdef CONF_WINC_USE_SPI + /* Must do this after global reset to set SPI data packet size. */ + nm_spi_init(); +#endif + ret = wait_for_bootrom(u8Mode); + if (M2M_SUCCESS != ret) { + goto ERR2; + } + + ret = wait_for_firmware_start(u8Mode); + if (M2M_SUCCESS != ret) { + goto ERR2; + } + + if((M2M_WIFI_MODE_ATE_HIGH == u8Mode)||(M2M_WIFI_MODE_ATE_LOW == u8Mode)) { + goto ERR1; + } else { + /*continue running*/ + } + + ret = enable_interrupts(); + if (M2M_SUCCESS != ret) { + M2M_ERR("failed to enable interrupts..\n"); + goto ERR2; + } + return ret; +ERR2: + nm_bus_iface_deinit(); +ERR1: + return ret; +} + +/* +* @fn nm_drv_deinit +* @brief Deinitialize NMC1000 driver +* @author M. Abdelmawla +* @date 17 July 2012 +* @version 1.0 +*/ +sint8 nm_drv_deinit(void * arg) +{ + sint8 ret; + + ret = chip_deinit(); + if (M2M_SUCCESS != ret) { + M2M_ERR("[nmi stop]: chip_deinit fail\n"); + goto ERR1; + } + + /* Disable SPI flash to save power when the chip is off */ + ret = spi_flash_enable(0); + if (M2M_SUCCESS != ret) { + M2M_ERR("[nmi stop]: SPI flash disable fail\n"); + goto ERR1; + } + + ret = nm_bus_iface_deinit(); + if (M2M_SUCCESS != ret) { + M2M_ERR("[nmi stop]: fail init bus\n"); + goto ERR1; + } +#ifdef CONF_WINC_USE_SPI + /* Must do this after global reset to set SPI data packet size. */ + nm_spi_deinit(); +#endif + +ERR1: + return ret; +} + + diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmdrv.h b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmdrv.h new file mode 100644 index 0000000000000..6a416b28e4534 --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmdrv.h @@ -0,0 +1,138 @@ +/** + * + * \file + * + * \brief This module contains NMC1500 M2M driver APIs declarations. + * + * Copyright (c) 2016-2017 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + +#ifndef _NMDRV_H_ +#define _NMDRV_H_ + +#include "common/include/nm_common.h" + +/** +* @struct tstrM2mRev +* @brief Structure holding firmware version parameters and build date/time +*/ +typedef struct { + uint32 u32Chipid; /* HW revision which will be basically the chip ID */ + uint8 u8FirmwareMajor; /* Version Major Number which represents the official release base */ + uint8 u8FirmwareMinor; /* Version Minor Number which represents the engineering release base */ + uint8 u8FirmwarePatch; /* Version pathc Number which represents the pathces release base */ + uint8 u8DriverMajor; /* Version Major Number which represents the official release base */ + uint8 u8DriverMinor; /* Version Minor Number which represents the engineering release base */ + uint8 u8DriverPatch; /* Version Patch Number which represents the pathces release base */ + uint8 BuildDate[sizeof(__DATE__)]; + uint8 BuildTime[sizeof(__TIME__)]; + uint8 _PAD8_; + uint16 u16FirmwareSvnNum; + uint16 _PAD16_[2]; +} tstrM2mRev; + +/** +* @struct tstrM2mBinaryHeader +* @brief Structure holding compatibility version info for firmware binaries +*/ +typedef struct { + tstrM2mRev binVerInfo; + uint32 flashOffset; + uint32 payloadSize; +} tstrM2mBinaryHeader; + +#ifdef __cplusplus + extern "C" { + #endif +/** +* @fn nm_get_firmware_info(tstrM2mRev* M2mRev) +* @brief Get Firmware version info +* @param [out] M2mRev +* pointer holds address of structure "tstrM2mRev" that contains the firmware version parameters +* @version 1.0 +*/ +sint8 nm_get_firmware_info(tstrM2mRev* M2mRev); +/** +* @fn nm_get_firmware_full_info(tstrM2mRev* pstrRev) +* @brief Get Firmware version info +* @param [out] M2mRev +* pointer holds address of structure "tstrM2mRev" that contains the firmware version parameters +* @version 1.0 +*/ +sint8 nm_get_firmware_full_info(tstrM2mRev* pstrRev); +/** +* @fn nm_get_ota_firmware_info(tstrM2mRev* pstrRev) +* @brief Get Firmware version info +* @param [out] M2mRev +* pointer holds address of structure "tstrM2mRev" that contains the firmware version parameters + +* @version 1.0 +*/ +sint8 nm_get_ota_firmware_info(tstrM2mRev* pstrRev); +/* +* @fn nm_drv_init +* @brief Initialize NMC1000 driver +* @return ZERO in case of success and Negative error code in case of failure +*/ +sint8 nm_drv_init_download_mode(void); + +/* +* @fn nm_drv_init +* @brief Initialize NMC1000 driver +* @return M2M_SUCCESS in case of success and Negative error code in case of failure +* @param [in] arg +* Generic argument TBD +* @return ZERO in case of success and Negative error code in case of failure + +*/ +sint8 nm_drv_init(void * arg); + +/** +* @fn nm_drv_deinit +* @brief Deinitialize NMC1000 driver +* @author M. Abdelmawla +* @param [in] arg +* Generic argument TBD +* @return ZERO in case of success and Negative error code in case of failure +*/ +sint8 nm_drv_deinit(void * arg); + +#ifdef __cplusplus + } + #endif + +#endif /*_NMDRV_H_*/ + + diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmi2c.c b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmi2c.c new file mode 100644 index 0000000000000..e11d2f795c15c --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmi2c.c @@ -0,0 +1,269 @@ +/** + * + * \file + * + * \brief This module contains NMC1000 I2C protocol bus APIs implementation. + * + * Copyright (c) 2016 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + +#include "common/include/nm_common.h" + +#ifdef CONF_WINC_USE_I2C + +#include "nmi2c.h" +#include "bus_wrapper/include/nm_bus_wrapper.h" + + +/* +* @fn nm_i2c_read_reg_with_ret +* @brief Read register with error code return +* @param [in] u32Addr +* Register address +* @param [out] pu32RetVal +* Pointer to u32 variable used to return the read value +* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure +* @author M. Abdelmawla +* @date 11 July 2012 +* @version 1.0 +*/ + sint8 nm_i2c_read_reg_with_ret(uint32 u32Addr, uint32* pu32RetVal) +{ + uint8 b[6]; + uint8 rsz; + tstrNmI2cDefault strI2c; + sint8 s8Ret = M2M_SUCCESS; + + if(u32Addr < 0xff) { /* clockless i2c */ + b[0] = 0x09; + b[1] = (uint8)(u32Addr); + rsz = 1; + strI2c.u16Sz = 2; + } else { + b[0] = 0x80; + b[1] = (uint8)(u32Addr >> 24); + b[2] = (uint8)(u32Addr >> 16); + b[3] = (uint8)(u32Addr >> 8); + b[4] = (uint8)(u32Addr); + b[5] = 0x04; + rsz = 4; + strI2c.u16Sz = 6; + } + + strI2c.pu8Buf = b; + + if(M2M_SUCCESS == nm_bus_ioctl(NM_BUS_IOCTL_W, &strI2c)) + { + strI2c.u16Sz = rsz; + if(M2M_SUCCESS != nm_bus_ioctl(NM_BUS_IOCTL_R, &strI2c)) + { + //M2M_ERR("read error\n"); + s8Ret = M2M_ERR_BUS_FAIL; + } + } + else + { + M2M_ERR("failed to send cfg bytes\n"); + s8Ret = M2M_ERR_BUS_FAIL; + } + + if (rsz == 1) { + *pu32RetVal = b[0]; + } else { + *pu32RetVal = b[0] | ((uint32)b[1] << 8) | ((uint32)b[2] << 16) | ((uint32)b[3] << 24); + } + return s8Ret; +} + +/* +* @fn nm_i2c_read_reg +* @brief Read register +* @param [in] u32Addr +* Register address +* @return Register value +* @author M. Abdelmawla +* @date 11 July 2012 +* @version 1.0 +*/ +uint32 nm_i2c_read_reg(uint32 u32Addr) +{ + uint32 val; + nm_i2c_read_reg_with_ret(u32Addr, &val); + return val; +} + +/* +* @fn nm_i2c_write_reg +* @brief write register +* @param [in] u32Addr +* Register address +* @param [in] u32Val +* Value to be written to the register +* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure +* @author M. Abdelmawla +* @date 11 July 2012 +* @version 1.0 +*/ +sint8 nm_i2c_write_reg(uint32 u32Addr, uint32 u32Val) +{ + tstrNmI2cDefault strI2c; + uint8 b[16]; + sint8 s8Ret = M2M_SUCCESS; + + if(u32Addr < 0xff) { /* clockless i2c */ + b[0] = 0x19; + b[1] = (uint8)(u32Addr); + b[2] = (uint8)(u32Val); + strI2c.u16Sz = 3; + } else { + b[0] = 0x90; + b[1] = (uint8)(u32Addr >> 24); + b[2] = (uint8)(u32Addr >> 16); + b[3] = (uint8)(u32Addr >> 8); + b[4] = (uint8)u32Addr; + b[5] = 0x04; + b[6] = (uint8)u32Val; + b[7] = (uint8)(u32Val >> 8); + b[8] = (uint8)(u32Val >> 16); + b[9] = (uint8)(u32Val >> 24); + strI2c.u16Sz = 10; + } + + strI2c.pu8Buf = b; + + if(M2M_SUCCESS != nm_bus_ioctl(NM_BUS_IOCTL_W, &strI2c)) + { + M2M_ERR("write error\n"); + s8Ret = M2M_ERR_BUS_FAIL; + } + + return s8Ret; +} + +/* +* @fn nm_i2c_read_block +* @brief Read block of data +* @param [in] u32Addr +* Start address +* @param [out] puBuf +* Pointer to a buffer used to return the read data +* @param [in] u16Sz +* Number of bytes to read. The buffer size must be >= u16Sz +* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure +* @author M. Abdelmawla +* @date 11 July 2012 +* @version 1.0 +*/ +sint8 nm_i2c_read_block(uint32 u32Addr, uint8 *pu8Buf, uint16 u16Sz) +{ + tstrNmI2cDefault strI2c; + uint8 au8Buf[7]; + sint8 s8Ret = M2M_SUCCESS; + + au8Buf[0] = 0x02; + au8Buf[1] = (uint8)(u32Addr >> 24); + au8Buf[2] = (uint8)(u32Addr >> 16); + au8Buf[3] = (uint8)(u32Addr >> 8); + au8Buf[4] = (uint8)(u32Addr >> 0); + au8Buf[5] = (uint8)(u16Sz >> 8); + au8Buf[6] = (uint8)(u16Sz); + + strI2c.pu8Buf = au8Buf; + strI2c.u16Sz = sizeof(au8Buf); + + if(M2M_SUCCESS != nm_bus_ioctl(NM_BUS_IOCTL_W, &strI2c)) + { + M2M_ERR("write error\n"); + s8Ret = M2M_ERR_BUS_FAIL; + } + else + { + strI2c.pu8Buf = pu8Buf; + strI2c.u16Sz = u16Sz; + + if(M2M_SUCCESS != nm_bus_ioctl(NM_BUS_IOCTL_R, &strI2c)) + { + M2M_ERR("read error\n"); + s8Ret = M2M_ERR_BUS_FAIL; + } + } + + return s8Ret; +} + +/* +* @fn nm_i2c_write_block +* @brief Write block of data +* @param [in] u32Addr +* Start address +* @param [in] puBuf +* Pointer to the buffer holding the data to be written +* @param [in] u16Sz +* Number of bytes to write. The buffer size must be >= u16Sz +* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure +* @author M. Abdelmawla +* @date 11 July 2012 +* @version 1.0 +*/ +sint8 nm_i2c_write_block(uint32 u32Addr, uint8 *pu8Buf, uint16 u16Sz) +{ + uint8 au8Buf[7]; + tstrNmI2cSpecial strI2c; + sint8 s8Ret = M2M_SUCCESS; + + au8Buf[0] = 0x12; + au8Buf[1] = (uint8)(u32Addr >> 24); + au8Buf[2] = (uint8)(u32Addr >> 16); + au8Buf[3] = (uint8)(u32Addr >> 8); + au8Buf[4] = (uint8)(u32Addr); + au8Buf[5] = (uint8)(u16Sz >> 8); + au8Buf[6] = (uint8)(u16Sz); + + strI2c.pu8Buf1 = au8Buf; + strI2c.pu8Buf2 = pu8Buf; + strI2c.u16Sz1 = sizeof(au8Buf); + strI2c.u16Sz2 = u16Sz; + + if(M2M_SUCCESS != nm_bus_ioctl(NM_BUS_IOCTL_W_SPECIAL, &strI2c)) + { + M2M_ERR("write error\n"); + s8Ret = M2M_ERR_BUS_FAIL; + } + + return s8Ret; +} + +#endif +/* EOF */ diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmi2c.h b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmi2c.h new file mode 100644 index 0000000000000..fea85e64c5ec5 --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmi2c.h @@ -0,0 +1,104 @@ +/** + * + * \file + * + * \brief This module contains NMC1000 I2C protocol bus APIs implementation. + * + * Copyright (c) 2016 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + +#ifndef _NMI2C_H_ +#define _NMI2C_H_ + +#include "common/include/nm_common.h" + +/** +* @fn nm_i2c_read_reg +* @brief Read register +* @param [in] u32Addr +* Register address +* @return Register value +*/ +uint32 nm_i2c_read_reg(uint32 u32Addr); + +/** +* @fn nm_i2c_read_reg_with_ret +* @brief Read register with error code return +* @param [in] u32Addr +* Register address +* @param [out] pu32RetVal +* Pointer to u32 variable used to return the read value +* @return ZERO in case of success and M2M_ERR_BUS_FAIL in case of failure +*/ +sint8 nm_i2c_read_reg_with_ret(uint32 u32Addr, uint32* pu32RetVal); + +/** +* @fn nm_i2c_write_reg +* @brief write register +* @param [in] u32Addr +* Register address +* @param [in] u32Val +* Value to be written to the register +* @return ZERO in case of success and M2M_ERR_BUS_FAIL in case of failure +*/ +sint8 nm_i2c_write_reg(uint32 u32Addr, uint32 u32Val); + +/** +* @fn nm_i2c_read_block +* @brief Read block of data +* @param [in] u32Addr +* Start address +* @param [out] puBuf +* Pointer to a buffer used to return the read data +* @param [in] u16Sz +* Number of bytes to read. The buffer size must be >= u16Sz +* @return ZERO in case of success and M2M_ERR_BUS_FAIL in case of failure +*/ +sint8 nm_i2c_read_block(uint32 u32Addr, uint8 *puBuf, uint16 u16Sz); + +/** +* @fn nm_i2c_write_block +* @brief Write block of data +* @param [in] u32Addr +* Start address +* @param [in] puBuf +* Pointer to the buffer holding the data to be written +* @param [in] u16Sz +* Number of bytes to write. The buffer size must be >= u16Sz +* @return ZERO in case of success and M2M_ERR_BUS_FAIL in case of failure +*/ +sint8 nm_i2c_write_block(uint32 u32Addr, uint8 *puBuf, uint16 u16Sz); + +#endif /* _NMI2C_H_ */ diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmspi.c b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmspi.c new file mode 100644 index 0000000000000..aa3dc6fe7a96b --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmspi.c @@ -0,0 +1,1390 @@ +/** + * + * \file + * + * \brief This module contains NMC1000 SPI protocol bus APIs implementation. + * + * Copyright (c) 2016-2017 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ +#include "common/include/nm_common.h" + +#ifdef CONF_WINC_USE_SPI + +#define USE_OLD_SPI_SW + +#include "bus_wrapper/include/nm_bus_wrapper.h" +#include "nmspi.h" + +#define NMI_PERIPH_REG_BASE 0x1000 +#define NMI_INTR_REG_BASE (NMI_PERIPH_REG_BASE+0xa00) +#define NMI_CHIPID (NMI_PERIPH_REG_BASE) +#define NMI_PIN_MUX_0 (NMI_PERIPH_REG_BASE + 0x408) +#define NMI_INTR_ENABLE (NMI_INTR_REG_BASE) + +#define NMI_SPI_REG_BASE 0xe800 +#define NMI_SPI_CTL (NMI_SPI_REG_BASE) +#define NMI_SPI_MASTER_DMA_ADDR (NMI_SPI_REG_BASE+0x4) +#define NMI_SPI_MASTER_DMA_COUNT (NMI_SPI_REG_BASE+0x8) +#define NMI_SPI_SLAVE_DMA_ADDR (NMI_SPI_REG_BASE+0xc) +#define NMI_SPI_SLAVE_DMA_COUNT (NMI_SPI_REG_BASE+0x10) +#define NMI_SPI_TX_MODE (NMI_SPI_REG_BASE+0x20) +#define NMI_SPI_PROTOCOL_CONFIG (NMI_SPI_REG_BASE+0x24) +#define NMI_SPI_INTR_CTL (NMI_SPI_REG_BASE+0x2c) +#define NMI_SPI_MISC_CTRL (NMI_SPI_REG_BASE+0x48) + +#define NMI_SPI_PROTOCOL_OFFSET (NMI_SPI_PROTOCOL_CONFIG-NMI_SPI_REG_BASE) + +#define SPI_BASE NMI_SPI_REG_BASE + +#define CMD_DMA_WRITE 0xc1 +#define CMD_DMA_READ 0xc2 +#define CMD_INTERNAL_WRITE 0xc3 +#define CMD_INTERNAL_READ 0xc4 +#define CMD_TERMINATE 0xc5 +#define CMD_REPEAT 0xc6 +#define CMD_DMA_EXT_WRITE 0xc7 +#define CMD_DMA_EXT_READ 0xc8 +#define CMD_SINGLE_WRITE 0xc9 +#define CMD_SINGLE_READ 0xca +#define CMD_RESET 0xcf + +#define N_OK 1 +#define N_FAIL 0 +#define N_RESET -1 +#define N_RETRY -2 + +#define SPI_RESP_RETRY_COUNT (10) +#define SPI_RETRY_COUNT (10) +#define DATA_PKT_SZ_256 256 +#define DATA_PKT_SZ_512 512 +#define DATA_PKT_SZ_1K 1024 +#define DATA_PKT_SZ_4K (4 * 1024) +#define DATA_PKT_SZ_8K (8 * 1024) +#define DATA_PKT_SZ DATA_PKT_SZ_8K + +static uint8 gu8Crc_off = 0; + +static sint8 nmi_spi_read(uint8* b, uint16 sz) +{ + tstrNmSpiRw spi; + spi.pu8InBuf = NULL; + spi.pu8OutBuf = b; + spi.u16Sz = sz; + return nm_bus_ioctl(NM_BUS_IOCTL_RW, &spi); +} + +static sint8 nmi_spi_write(uint8* b, uint16 sz) +{ + tstrNmSpiRw spi; + spi.pu8InBuf = b; + spi.pu8OutBuf = NULL; + spi.u16Sz = sz; + return nm_bus_ioctl(NM_BUS_IOCTL_RW, &spi); +} +#ifndef USE_OLD_SPI_SW +static sint8 nmi_spi_rw(uint8 *bin,uint8* bout,uint16 sz) +{ + tstrNmSpiRw spi; + spi.pu8InBuf = bin; + spi.pu8OutBuf = bout; + spi.u16Sz = sz; + return nm_bus_ioctl(NM_BUS_IOCTL_RW, &spi); +} +#endif +/******************************************** + + Crc7 + +********************************************/ + +static const uint8 crc7_syndrome_table[256] = { + 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, + 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77, + 0x19, 0x10, 0x0b, 0x02, 0x3d, 0x34, 0x2f, 0x26, + 0x51, 0x58, 0x43, 0x4a, 0x75, 0x7c, 0x67, 0x6e, + 0x32, 0x3b, 0x20, 0x29, 0x16, 0x1f, 0x04, 0x0d, + 0x7a, 0x73, 0x68, 0x61, 0x5e, 0x57, 0x4c, 0x45, + 0x2b, 0x22, 0x39, 0x30, 0x0f, 0x06, 0x1d, 0x14, + 0x63, 0x6a, 0x71, 0x78, 0x47, 0x4e, 0x55, 0x5c, + 0x64, 0x6d, 0x76, 0x7f, 0x40, 0x49, 0x52, 0x5b, + 0x2c, 0x25, 0x3e, 0x37, 0x08, 0x01, 0x1a, 0x13, + 0x7d, 0x74, 0x6f, 0x66, 0x59, 0x50, 0x4b, 0x42, + 0x35, 0x3c, 0x27, 0x2e, 0x11, 0x18, 0x03, 0x0a, + 0x56, 0x5f, 0x44, 0x4d, 0x72, 0x7b, 0x60, 0x69, + 0x1e, 0x17, 0x0c, 0x05, 0x3a, 0x33, 0x28, 0x21, + 0x4f, 0x46, 0x5d, 0x54, 0x6b, 0x62, 0x79, 0x70, + 0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31, 0x38, + 0x41, 0x48, 0x53, 0x5a, 0x65, 0x6c, 0x77, 0x7e, + 0x09, 0x00, 0x1b, 0x12, 0x2d, 0x24, 0x3f, 0x36, + 0x58, 0x51, 0x4a, 0x43, 0x7c, 0x75, 0x6e, 0x67, + 0x10, 0x19, 0x02, 0x0b, 0x34, 0x3d, 0x26, 0x2f, + 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, + 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, + 0x6a, 0x63, 0x78, 0x71, 0x4e, 0x47, 0x5c, 0x55, + 0x22, 0x2b, 0x30, 0x39, 0x06, 0x0f, 0x14, 0x1d, + 0x25, 0x2c, 0x37, 0x3e, 0x01, 0x08, 0x13, 0x1a, + 0x6d, 0x64, 0x7f, 0x76, 0x49, 0x40, 0x5b, 0x52, + 0x3c, 0x35, 0x2e, 0x27, 0x18, 0x11, 0x0a, 0x03, + 0x74, 0x7d, 0x66, 0x6f, 0x50, 0x59, 0x42, 0x4b, + 0x17, 0x1e, 0x05, 0x0c, 0x33, 0x3a, 0x21, 0x28, + 0x5f, 0x56, 0x4d, 0x44, 0x7b, 0x72, 0x69, 0x60, + 0x0e, 0x07, 0x1c, 0x15, 0x2a, 0x23, 0x38, 0x31, + 0x46, 0x4f, 0x54, 0x5d, 0x62, 0x6b, 0x70, 0x79 +}; + + +static uint8 crc7_byte(uint8 crc, uint8 data) +{ + return crc7_syndrome_table[(crc << 1) ^ data]; +} + +static uint8 crc7(uint8 crc, const uint8 *buffer, uint32 len) +{ + while (len--) + crc = crc7_byte(crc, *buffer++); + return crc; +} + +/******************************************** + + Spi protocol Function + +********************************************/ + +#define CMD_DMA_WRITE 0xc1 +#define CMD_DMA_READ 0xc2 +#define CMD_INTERNAL_WRITE 0xc3 +#define CMD_INTERNAL_READ 0xc4 +#define CMD_TERMINATE 0xc5 +#define CMD_REPEAT 0xc6 +#define CMD_DMA_EXT_WRITE 0xc7 +#define CMD_DMA_EXT_READ 0xc8 +#define CMD_SINGLE_WRITE 0xc9 +#define CMD_SINGLE_READ 0xca +#define CMD_RESET 0xcf + +#define DATA_PKT_SZ_256 256 +#define DATA_PKT_SZ_512 512 +#define DATA_PKT_SZ_1K 1024 +#define DATA_PKT_SZ_4K (4 * 1024) +#define DATA_PKT_SZ_8K (8 * 1024) +#define DATA_PKT_SZ DATA_PKT_SZ_8K + +static sint8 spi_cmd(uint8 cmd, uint32 adr, uint32 u32data, uint32 sz,uint8 clockless) +{ + uint8 bc[9]; + uint8 len = 5; + sint8 result = N_OK; + + bc[0] = cmd; + switch (cmd) { + case CMD_SINGLE_READ: /* single word (4 bytes) read */ + bc[1] = (uint8)(adr >> 16); + bc[2] = (uint8)(adr >> 8); + bc[3] = (uint8)adr; + len = 5; + break; + case CMD_INTERNAL_READ: /* internal register read */ + bc[1] = (uint8)(adr >> 8); + if(clockless) bc[1] |= (1 << 7); + bc[2] = (uint8)adr; + bc[3] = 0x00; + len = 5; + break; + case CMD_TERMINATE: /* termination */ + bc[1] = 0x00; + bc[2] = 0x00; + bc[3] = 0x00; + len = 5; + break; + case CMD_REPEAT: /* repeat */ + bc[1] = 0x00; + bc[2] = 0x00; + bc[3] = 0x00; + len = 5; + break; + case CMD_RESET: /* reset */ + bc[1] = 0xff; + bc[2] = 0xff; + bc[3] = 0xff; + len = 5; + break; + case CMD_DMA_WRITE: /* dma write */ + case CMD_DMA_READ: /* dma read */ + bc[1] = (uint8)(adr >> 16); + bc[2] = (uint8)(adr >> 8); + bc[3] = (uint8)adr; + bc[4] = (uint8)(sz >> 8); + bc[5] = (uint8)(sz); + len = 7; + break; + case CMD_DMA_EXT_WRITE: /* dma extended write */ + case CMD_DMA_EXT_READ: /* dma extended read */ + bc[1] = (uint8)(adr >> 16); + bc[2] = (uint8)(adr >> 8); + bc[3] = (uint8)adr; + bc[4] = (uint8)(sz >> 16); + bc[5] = (uint8)(sz >> 8); + bc[6] = (uint8)(sz); + len = 8; + break; + case CMD_INTERNAL_WRITE: /* internal register write */ + bc[1] = (uint8)(adr >> 8); + if(clockless) bc[1] |= (1 << 7); + bc[2] = (uint8)(adr); + bc[3] = (uint8)(u32data >> 24); + bc[4] = (uint8)(u32data >> 16); + bc[5] = (uint8)(u32data >> 8); + bc[6] = (uint8)(u32data); + len = 8; + break; + case CMD_SINGLE_WRITE: /* single word write */ + bc[1] = (uint8)(adr >> 16); + bc[2] = (uint8)(adr >> 8); + bc[3] = (uint8)(adr); + bc[4] = (uint8)(u32data >> 24); + bc[5] = (uint8)(u32data >> 16); + bc[6] = (uint8)(u32data >> 8); + bc[7] = (uint8)(u32data); + len = 9; + break; + default: + result = N_FAIL; + break; + } + + if (result) { + if (!gu8Crc_off) + bc[len-1] = (crc7(0x7f, (const uint8 *)&bc[0], len-1)) << 1; + else + len-=1; + + if (M2M_SUCCESS != nmi_spi_write(bc, len)) { + M2M_ERR("[nmi spi]: Failed cmd write, bus error...\n"); + result = N_FAIL; + } + } + + return result; +} + +static sint8 spi_data_rsp(uint8 cmd) +{ + uint8 len; + uint8 rsp[3]; + sint8 result = N_OK; + + if (!gu8Crc_off) + len = 2; + else + len = 3; + + if (M2M_SUCCESS != nmi_spi_read(&rsp[0], len)) { + M2M_ERR("[nmi spi]: Failed bus error...\n"); + result = N_FAIL; + goto _fail_; + } + + if((rsp[len-1] != 0)||(rsp[len-2] != 0xC3)) + { + M2M_ERR("[nmi spi]: Failed data response read, %x %x %x\n",rsp[0],rsp[1],rsp[2]); + result = N_FAIL; + goto _fail_; + } +_fail_: + + return result; +} + +static sint8 spi_cmd_rsp(uint8 cmd) +{ + uint8 rsp; + sint8 result = N_OK; + sint8 s8RetryCnt; + + /** + Command/Control response + **/ + if ((cmd == CMD_RESET) || + (cmd == CMD_TERMINATE) || + (cmd == CMD_REPEAT)) { + if (M2M_SUCCESS != nmi_spi_read(&rsp, 1)) { + result = N_FAIL; + goto _fail_; + } + } + + /* wait for response */ + s8RetryCnt = SPI_RESP_RETRY_COUNT; + do + { + if (M2M_SUCCESS != nmi_spi_read(&rsp, 1)) { + M2M_ERR("[nmi spi]: Failed cmd response read, bus error...\n"); + result = N_FAIL; + goto _fail_; + } + } while((rsp != cmd) && (s8RetryCnt-- >0)); + + /** + State response + **/ + /* wait for response */ + s8RetryCnt = SPI_RESP_RETRY_COUNT; + do + { + if (M2M_SUCCESS != nmi_spi_read(&rsp, 1)) { + M2M_ERR("[nmi spi]: Failed cmd response read, bus error...\n"); + result = N_FAIL; + goto _fail_; + } + } while((rsp != 0x00) && (s8RetryCnt-- >0)); + +_fail_: + + return result; +} +#ifndef USE_OLD_SPI_SW +static int spi_cmd_complete(uint8_t cmd, uint32_t adr, uint8_t *b, uint32_t sz, uint8_t clockless) +{ + uint8_t wb[32], rb[32]; + uint8_t wix, rix; + uint32_t len2; + uint8_t rsp; + int len = 0; + int result = N_OK; + + wb[0] = cmd; + switch (cmd) { + case CMD_SINGLE_READ: /* single word (4 bytes) read */ + wb[1] = (uint8_t)(adr >> 16); + wb[2] = (uint8_t)(adr >> 8); + wb[3] = (uint8_t)adr; + len = 5; + break; + case CMD_INTERNAL_READ: /* internal register read */ + wb[1] = (uint8_t)(adr >> 8); + if(clockless == 1) wb[1] |= (1 << 7); + wb[2] = (uint8_t)adr; + wb[3] = 0x00; + len = 5; + break; + case CMD_TERMINATE: /* termination */ + wb[1] = 0x00; + wb[2] = 0x00; + wb[3] = 0x00; + len = 5; + break; + case CMD_REPEAT: /* repeat */ + wb[1] = 0x00; + wb[2] = 0x00; + wb[3] = 0x00; + len = 5; + break; + case CMD_RESET: /* reset */ + wb[1] = 0xff; + wb[2] = 0xff; + wb[3] = 0xff; + len = 5; + break; + case CMD_DMA_WRITE: /* dma write */ + case CMD_DMA_READ: /* dma read */ + wb[1] = (uint8_t)(adr >> 16); + wb[2] = (uint8_t)(adr >> 8); + wb[3] = (uint8_t)adr; + wb[4] = (uint8_t)(sz >> 8); + wb[5] = (uint8_t)(sz); + len = 7; + break; + case CMD_DMA_EXT_WRITE: /* dma extended write */ + case CMD_DMA_EXT_READ: /* dma extended read */ + wb[1] = (uint8_t)(adr >> 16); + wb[2] = (uint8_t)(adr >> 8); + wb[3] = (uint8_t)adr; + wb[4] = (uint8_t)(sz >> 16); + wb[5] = (uint8_t)(sz >> 8); + wb[6] = (uint8_t)(sz); + len = 8; + break; + case CMD_INTERNAL_WRITE: /* internal register write */ + wb[1] = (uint8_t)(adr >> 8); + if(clockless == 1) wb[1] |= (1 << 7); + wb[2] = (uint8_t)(adr); + wb[3] = b[3]; + wb[4] = b[2]; + wb[5] = b[1]; + wb[6] = b[0]; + len = 8; + break; + case CMD_SINGLE_WRITE: /* single word write */ + wb[1] = (uint8_t)(adr >> 16); + wb[2] = (uint8_t)(adr >> 8); + wb[3] = (uint8_t)(adr); + wb[4] = b[3]; + wb[5] = b[2]; + wb[6] = b[1]; + wb[7] = b[0]; + len = 9; + break; + default: + result = N_FAIL; + break; + } + + if (result != N_OK) { + return result; + } + + if (!gu8Crc_off) { + wb[len-1] = (crc7(0x7f, (const uint8_t *)&wb[0], len-1)) << 1; + } else { + len -=1; + } + +#define NUM_SKIP_BYTES (1) +#define NUM_RSP_BYTES (2) +#define NUM_DATA_HDR_BYTES (1) +#define NUM_DATA_BYTES (4) +#define NUM_CRC_BYTES (2) +#define NUM_DUMMY_BYTES (3) + + if ((cmd == CMD_RESET) || + (cmd == CMD_TERMINATE) || + (cmd == CMD_REPEAT)) { + len2 = len + (NUM_SKIP_BYTES + NUM_RSP_BYTES + NUM_DUMMY_BYTES); + } else if ((cmd == CMD_INTERNAL_READ) || (cmd == CMD_SINGLE_READ)) { + if (!gu8Crc_off) { + len2 = len + (NUM_RSP_BYTES + NUM_DATA_HDR_BYTES + NUM_DATA_BYTES + + NUM_CRC_BYTES + NUM_DUMMY_BYTES); + } else { + len2 = len + (NUM_RSP_BYTES + NUM_DATA_HDR_BYTES + NUM_DATA_BYTES + + NUM_DUMMY_BYTES); + } + } else { + len2 = len + (NUM_RSP_BYTES + NUM_DUMMY_BYTES); + } +#undef NUM_DUMMY_BYTES + + if(len2 > (sizeof(wb)/sizeof(wb[0]))) { + M2M_ERR("[nmi spi]: spi buffer size too small (%d) (%d)\n", + len2, (sizeof(wb)/sizeof(wb[0]))); + result = N_FAIL; + return result; + } + /* zero spi write buffers. */ + for(wix = len; wix< len2; wix++) { + wb[wix] = 0; + } + rix = len; + + if (nmi_spi_rw(wb, rb, len2) != M2M_SUCCESS) { + M2M_ERR("[nmi spi]: Failed cmd write, bus error...\n"); + result = N_FAIL; + return result; + } + +#if 0 + { + int jj; + printk("--- cnd = %x, len=%d, len2=%d\n", cmd, len, len2); + for(jj=0; jj= len2) break; + if(((jj+1)%16) != 0) { + if((jj%16) == 0) { + printk("wb[%02x]: %02x ", jj, wb[jj]); + } else { + printk("%02x ", wb[jj]); + } + } else { + printk("%02x\n", wb[jj]); + } + } + printk("\n"); + + for(jj=0; jj= len2) break; + if(((jj+1)%16) != 0) { + if((jj%16) == 0) { + printk("rb[%02x]: %02x ", jj, rb[jj]); + } else { + printk("%02x ", rb[jj]); + } + } else { + printk("%02x\n", rb[jj]); + } + } + printk("\n"); + } +#endif + + /** + Command/Control response + **/ + if ((cmd == CMD_RESET) || + (cmd == CMD_TERMINATE) || + (cmd == CMD_REPEAT)) { + rix++; /* skip 1 byte */ + } + + rsp = rb[rix++]; + + + if (rsp != cmd) { + M2M_ERR("[nmi spi]: Failed cmd response, cmd (%02x), resp (%02x)\n", cmd, rsp); + result = N_FAIL; + return result; + } + + /** + State response + **/ + rsp = rb[rix++]; + if (rsp != 0x00) { + M2M_ERR("[nmi spi]: Failed cmd state response state (%02x)\n", rsp); + result = N_FAIL; + return result; + } + + if ((cmd == CMD_INTERNAL_READ) || (cmd == CMD_SINGLE_READ) + || (cmd == CMD_DMA_READ) || (cmd == CMD_DMA_EXT_READ)) { + int retry; + //uint16_t crc1, crc2; + uint8_t crc[2]; + /** + Data Respnose header + **/ + retry = SPI_RESP_RETRY_COUNT; + do { + /* ensure there is room in buffer later to read data and crc */ + if(rix < len2) { + rsp = rb[rix++]; + } else { + retry = 0; + break; + } + if (((rsp >> 4) & 0xf) == 0xf) + break; + } while (retry--); + + if (retry <= 0) { + M2M_ERR("[nmi spi]: Error, data read response (%02x)\n", rsp); + result = N_RESET; + return result; + } + + if ((cmd == CMD_INTERNAL_READ) || (cmd == CMD_SINGLE_READ)) { + /** + Read bytes + **/ + if((rix+3) < len2) { + b[0] = rb[rix++]; + b[1] = rb[rix++]; + b[2] = rb[rix++]; + b[3] = rb[rix++]; + } else { + M2M_ERR("[nmi spi]: buffer overrun when reading data.\n"); + result = N_FAIL; + return result; + } + + if (!gu8Crc_off) { + /** + Read Crc + **/ + if((rix+1) < len2) { + crc[0] = rb[rix++]; + crc[1] = rb[rix++]; + } else { + M2M_ERR("[nmi spi]: buffer overrun when reading crc.\n"); + result = N_FAIL; + return result; + } + } + } else if((cmd == CMD_DMA_READ) || (cmd == CMD_DMA_EXT_READ)) { + int ix; + + /* some data may be read in response to dummy bytes. */ + for(ix=0; (rix < len2) && (ix < sz);) { + b[ix++] = rb[rix++]; + } +#if 0 + if(ix) M2M_INFO("ttt %d %d\n", sz, ix); +#endif + sz -= ix; + + if(sz > 0) { + int nbytes; + + if (sz <= (DATA_PKT_SZ-ix)) { + nbytes = sz; + } else { + nbytes = DATA_PKT_SZ-ix; + } + + /** + Read bytes + **/ + if (nmi_spi_read(&b[ix], nbytes) != M2M_SUCCESS) { + M2M_ERR("[nmi spi]: Failed data block read, bus error...\n"); + result = N_FAIL; + goto _error_; + } + + /** + Read Crc + **/ + if (!gu8Crc_off) { + if (nmi_spi_read(crc, 2) != M2M_SUCCESS) { + M2M_ERR("[nmi spi]: Failed data block crc read, bus error...\n"); + result = N_FAIL; + goto _error_; + } + } + + + ix += nbytes; + sz -= nbytes; + } + + /* if any data in left unread, then read the rest using normal DMA code.*/ + while(sz > 0) { + int nbytes; + + if (sz <= DATA_PKT_SZ) { + nbytes = sz; + } else { + nbytes = DATA_PKT_SZ; + } + + /** + read data response only on the next DMA cycles not + the first DMA since data response header is already + handled above for the first DMA. + **/ + /** + Data Respnose header + **/ + retry = SPI_RESP_RETRY_COUNT; + do { + if (nmi_spi_read(&rsp, 1) != M2M_SUCCESS) { + M2M_ERR("[nmi spi]: Failed data response read, bus error...\n"); + result = N_FAIL; + break; + } + if (((rsp >> 4) & 0xf) == 0xf) + break; + } while (retry--); + + if (result == N_FAIL) + break; + + + /** + Read bytes + **/ + if (nmi_spi_read(&b[ix], nbytes) != M2M_SUCCESS) { + M2M_ERR("[nmi spi]: Failed data block read, bus error...\n"); + result = N_FAIL; + break; + } + + /** + Read Crc + **/ + if (!gu8Crc_off) { + if (nmi_spi_read(crc, 2) != M2M_SUCCESS) { + M2M_ERR("[nmi spi]: Failed data block crc read, bus error...\n"); + result = N_FAIL; + break; + } + } + + ix += nbytes; + sz -= nbytes; + } + } + } +_error_: + return result; +} +#endif +static sint8 spi_data_read(uint8 *b, uint16 sz,uint8 clockless) +{ + sint16 retry, ix, nbytes; + sint8 result = N_OK; + uint8 crc[2]; + uint8 rsp; + + /** + Data + **/ + ix = 0; + do { + if (sz <= DATA_PKT_SZ) + nbytes = sz; + else + nbytes = DATA_PKT_SZ; + + /** + Data Respnose header + **/ + retry = SPI_RESP_RETRY_COUNT; + do { + if (M2M_SUCCESS != nmi_spi_read(&rsp, 1)) { + M2M_ERR("[nmi spi]: Failed data response read, bus error...\n"); + result = N_FAIL; + break; + } + if (((rsp >> 4) & 0xf) == 0xf) + break; + } while (retry--); + + if (result == N_FAIL) + break; + + if (retry <= 0) { + M2M_ERR("[nmi spi]: Failed data response read...(%02x)\n", rsp); + result = N_FAIL; + break; + } + + /** + Read bytes + **/ + if (M2M_SUCCESS != nmi_spi_read(&b[ix], nbytes)) { + M2M_ERR("[nmi spi]: Failed data block read, bus error...\n"); + result = N_FAIL; + break; + } + if(!clockless) + { + /** + Read Crc + **/ + if (!gu8Crc_off) { + if (M2M_SUCCESS != nmi_spi_read(crc, 2)) { + M2M_ERR("[nmi spi]: Failed data block crc read, bus error...\n"); + result = N_FAIL; + break; + } + } + } + ix += nbytes; + sz -= nbytes; + + } while (sz); + + return result; +} + +static sint8 spi_data_write(uint8 *b, uint16 sz) +{ + sint16 ix; + uint16 nbytes; + sint8 result = 1; + uint8 cmd, order, crc[2] = {0}; + //uint8 rsp; + + /** + Data + **/ + ix = 0; + do { + if (sz <= DATA_PKT_SZ) + nbytes = sz; + else + nbytes = DATA_PKT_SZ; + + /** + Write command + **/ + cmd = 0xf0; + if (ix == 0) { + if (sz <= DATA_PKT_SZ) + order = 0x3; + else + order = 0x1; + } else { + if (sz <= DATA_PKT_SZ) + order = 0x3; + else + order = 0x2; + } + cmd |= order; + if (M2M_SUCCESS != nmi_spi_write(&cmd, 1)) { + M2M_ERR("[nmi spi]: Failed data block cmd write, bus error...\n"); + result = N_FAIL; + break; + } + + /** + Write data + **/ + if (M2M_SUCCESS != nmi_spi_write(&b[ix], nbytes)) { + M2M_ERR("[nmi spi]: Failed data block write, bus error...\n"); + result = N_FAIL; + break; + } + + /** + Write Crc + **/ + if (!gu8Crc_off) { + if (M2M_SUCCESS != nmi_spi_write(crc, 2)) { + M2M_ERR("[nmi spi]: Failed data block crc write, bus error...\n"); + result = N_FAIL; + break; + } + } + + ix += nbytes; + sz -= nbytes; + } while (sz); + + + return result; +} + +/******************************************** + + Spi Internal Read/Write Function + +********************************************/ + +/******************************************** + + Spi interfaces + +********************************************/ + +static sint8 spi_write_reg(uint32 addr, uint32 u32data) +{ + uint8 retry = SPI_RETRY_COUNT; + sint8 result = N_OK; + uint8 cmd = CMD_SINGLE_WRITE; + uint8 clockless = 0; + +_RETRY_: + if (addr <= 0x30) + { + /** + NMC1000 clockless registers. + **/ + cmd = CMD_INTERNAL_WRITE; + clockless = 1; + } + else + { + cmd = CMD_SINGLE_WRITE; + clockless = 0; + } + +#if defined USE_OLD_SPI_SW + result = spi_cmd(cmd, addr, u32data, 4, clockless); + if (result != N_OK) { + M2M_ERR("[nmi spi]: Failed cmd, write reg (%08x)...\n", (unsigned int)addr); + goto _FAIL_; + } + + result = spi_cmd_rsp(cmd); + if (result != N_OK) { + M2M_ERR("[nmi spi]: Failed cmd response, write reg (%08x)...\n", (unsigned int)addr); + goto _FAIL_; + } + +#else + + result = spi_cmd_complete(cmd, addr, (uint8*)&u32data, 4, clockless); + if (result != N_OK) { + M2M_ERR( "[nmi spi]: Failed cmd, write reg (%08x)...\n", addr); + goto _FAIL_; + } + +#endif +_FAIL_: + if(result != N_OK) + { + nm_bsp_sleep(1); + spi_cmd(CMD_RESET, 0, 0, 0, 0); + spi_cmd_rsp(CMD_RESET); + M2M_ERR("Reset and retry %d %lx %lx\n",retry,addr,u32data); + nm_bsp_sleep(1); + retry--; + if(retry) goto _RETRY_; + } + + return result; +} + +static sint8 nm_spi_write(uint32 addr, uint8 *buf, uint16 size) +{ + sint8 result; + uint8 retry = SPI_RETRY_COUNT; + uint8 cmd = CMD_DMA_EXT_WRITE; + + +_RETRY_: + /** + Command + **/ +#if defined USE_OLD_SPI_SW + //Workaround hardware problem with single byte transfers over SPI bus + if (size == 1) + size = 2; + + result = spi_cmd(cmd, addr, 0, size,0); + if (result != N_OK) { + M2M_ERR("[nmi spi]: Failed cmd, write block (%08x)...\n", (unsigned int)addr); + goto _FAIL_; + } + + result = spi_cmd_rsp(cmd); + if (result != N_OK) { + M2M_ERR("[nmi spi ]: Failed cmd response, write block (%08x)...\n", (unsigned int)addr); + goto _FAIL_; + } +#else + result = spi_cmd_complete(cmd, addr, NULL, size, 0); + if (result != N_OK) { + M2M_ERR( "[nmi spi]: Failed cmd, write block (%08x)...\n", addr); + goto _FAIL_; + } +#endif + + /** + Data + **/ + result = spi_data_write(buf, size); + if (result != N_OK) { + M2M_ERR("[nmi spi]: Failed block data write...\n"); + goto _FAIL_; + } + /** + Data RESP + **/ + result = spi_data_rsp(cmd); + if (result != N_OK) { + M2M_ERR("[nmi spi]: Failed block data write...\n"); + goto _FAIL_; + } + +_FAIL_: + if(result != N_OK) + { + nm_bsp_sleep(1); + spi_cmd(CMD_RESET, 0, 0, 0, 0); + spi_cmd_rsp(CMD_RESET); + M2M_ERR("Reset and retry %d %lx %d\n",retry,addr,size); + nm_bsp_sleep(1); + retry--; + if(retry) goto _RETRY_; + } + + + return result; +} + +static sint8 spi_read_reg(uint32 addr, uint32 *u32data) +{ + uint8 retry = SPI_RETRY_COUNT; + sint8 result = N_OK; + uint8 cmd = CMD_SINGLE_READ; + uint8 tmp[4]; + uint8 clockless = 0; + +_RETRY_: + + if (addr <= 0xff) + { + /** + NMC1000 clockless registers. + **/ + cmd = CMD_INTERNAL_READ; + clockless = 1; + } + else + { + cmd = CMD_SINGLE_READ; + clockless = 0; + } + +#if defined USE_OLD_SPI_SW + result = spi_cmd(cmd, addr, 0, 4, clockless); + if (result != N_OK) { + M2M_ERR("[nmi spi]: Failed cmd, read reg (%08x)...\n", (unsigned int)addr); + goto _FAIL_; + } + + result = spi_cmd_rsp(cmd); + if (result != N_OK) { + M2M_ERR("[nmi spi]: Failed cmd response, read reg (%08x)...\n", (unsigned int)addr); + goto _FAIL_; + } + + /* to avoid endianess issues */ + result = spi_data_read(&tmp[0], 4, clockless); + if (result != N_OK) { + M2M_ERR("[nmi spi]: Failed data read...\n"); + goto _FAIL_; + } +#else + result = spi_cmd_complete(cmd, addr, (uint8*)&tmp[0], 4, clockless); + if (result != N_OK) { + M2M_ERR( "[nmi spi]: Failed cmd, read reg (%08x)...\n", addr); + goto _FAIL_; + } + +#endif + + *u32data = tmp[0] | + ((uint32)tmp[1] << 8) | + ((uint32)tmp[2] << 16) | + ((uint32)tmp[3] << 24); + +_FAIL_: + if(result != N_OK) + { + + nm_bsp_sleep(1); + spi_cmd(CMD_RESET, 0, 0, 0, 0); + spi_cmd_rsp(CMD_RESET); + M2M_ERR("Reset and retry %d %lx\n",retry,addr); + nm_bsp_sleep(1); + retry--; + if(retry) goto _RETRY_; + } + + return result; +} + +static sint8 nm_spi_read(uint32 addr, uint8 *buf, uint16 size) +{ + uint8 cmd = CMD_DMA_EXT_READ; + sint8 result; + uint8 retry = SPI_RETRY_COUNT; +#if defined USE_OLD_SPI_SW + uint8 tmp[2]; + uint8 single_byte_workaround = 0; +#endif + +_RETRY_: + + /** + Command + **/ +#if defined USE_OLD_SPI_SW + if (size == 1) + { + //Workaround hardware problem with single byte transfers over SPI bus + size = 2; + single_byte_workaround = 1; + } + result = spi_cmd(cmd, addr, 0, size,0); + if (result != N_OK) { + M2M_ERR("[nmi spi]: Failed cmd, read block (%08x)...\n", (unsigned int)addr); + goto _FAIL_; + } + + result = spi_cmd_rsp(cmd); + if (result != N_OK) { + M2M_ERR("[nmi spi]: Failed cmd response, read block (%08x)...\n", (unsigned int)addr); + goto _FAIL_; + } + + /** + Data + **/ + if (single_byte_workaround) + { + result = spi_data_read(tmp, size,0); + buf[0] = tmp[0]; + } + else + result = spi_data_read(buf, size,0); + + if (result != N_OK) { + M2M_ERR("[nmi spi]: Failed block data read...\n"); + goto _FAIL_; + } +#else + result = spi_cmd_complete(cmd, addr, buf, size, 0); + if (result != N_OK) { + M2M_ERR("[nmi spi]: Failed cmd, read block (%08x)...\n", addr); + goto _FAIL_; + } +#endif + +_FAIL_: + if(result != N_OK) + { + nm_bsp_sleep(1); + spi_cmd(CMD_RESET, 0, 0, 0, 0); + spi_cmd_rsp(CMD_RESET); + M2M_ERR("Reset and retry %d %lx %d\n",retry,addr,size); + nm_bsp_sleep(1); + retry--; + if(retry) goto _RETRY_; + } + + return result; +} + +/******************************************** + + Bus interfaces + +********************************************/ + +static void spi_init_pkt_sz(void) +{ + uint32 val32; + + /* Make sure SPI max. packet size fits the defined DATA_PKT_SZ. */ + val32 = nm_spi_read_reg(SPI_BASE+0x24); + val32 &= ~(0x7 << 4); + switch(DATA_PKT_SZ) + { + case 256: val32 |= (0 << 4); break; + case 512: val32 |= (1 << 4); break; + case 1024: val32 |= (2 << 4); break; + case 2048: val32 |= (3 << 4); break; + case 4096: val32 |= (4 << 4); break; + case 8192: val32 |= (5 << 4); break; + + } + nm_spi_write_reg(SPI_BASE+0x24, val32); +} + +sint8 nm_spi_reset(void) +{ + spi_cmd(CMD_RESET, 0, 0, 0, 0); + spi_cmd_rsp(CMD_RESET); + return M2M_SUCCESS; +} + +/* +* @fn nm_spi_init +* @brief Initialize the SPI +* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure +* @author M. Abdelmawla +* @date 11 July 2012 +* @version 1.0 +*/ +sint8 nm_spi_init(void) +{ + uint32 chipid; + uint32 reg = 0; + + + /** + configure protocol + **/ + gu8Crc_off = 0; + + // TODO: We can remove the CRC trials if there is a definite way to reset + // the SPI to it's initial value. + if (!spi_read_reg(NMI_SPI_PROTOCOL_CONFIG, ®)) { + /* Read failed. Try with CRC off. This might happen when module + is removed but chip isn't reset*/ + gu8Crc_off = 1; + M2M_ERR("[nmi spi]: Failed internal read protocol with CRC on, retyring with CRC off...\n"); + if (!spi_read_reg(NMI_SPI_PROTOCOL_CONFIG, ®)){ + // Reaad failed with both CRC on and off, something went bad + M2M_ERR( "[nmi spi]: Failed internal read protocol...\n"); + return 0; + } + } + if(gu8Crc_off == 0) + { + reg &= ~0xc; /* disable crc checking */ + reg &= ~0x70; + reg |= (0x5 << 4); + if (!spi_write_reg(NMI_SPI_PROTOCOL_CONFIG, reg)) { + M2M_ERR( "[nmi spi]: Failed internal write protocol reg...\n"); + return 0; + } + gu8Crc_off = 1; + } + + /** + make sure can read back chip id correctly + **/ + if (!spi_read_reg(0x1000, &chipid)) { + M2M_ERR("[nmi spi]: Fail cmd read chip id...\n"); + return M2M_ERR_BUS_FAIL; + } + + M2M_DBG("[nmi spi]: chipid (%08x)\n", (unsigned int)chipid); + spi_init_pkt_sz(); + + + return M2M_SUCCESS; +} + +/* +* @fn nm_spi_init +* @brief DeInitialize the SPI +* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure +* @author Samer Sarhan +* @date 27 Feb 2015 +* @version 1.0 +*/ +sint8 nm_spi_deinit(void) +{ + gu8Crc_off = 0; + return M2M_SUCCESS; +} + +/* +* @fn nm_spi_read_reg +* @brief Read register +* @param [in] u32Addr +* Register address +* @return Register value +* @author M. Abdelmawla +* @date 11 July 2012 +* @version 1.0 +*/ +uint32 nm_spi_read_reg(uint32 u32Addr) +{ + uint32 u32Val; + + spi_read_reg(u32Addr, &u32Val); + + return u32Val; +} + +/* +* @fn nm_spi_read_reg_with_ret +* @brief Read register with error code return +* @param [in] u32Addr +* Register address +* @param [out] pu32RetVal +* Pointer to u32 variable used to return the read value +* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure +* @author M. Abdelmawla +* @date 11 July 2012 +* @version 1.0 +*/ +sint8 nm_spi_read_reg_with_ret(uint32 u32Addr, uint32* pu32RetVal) +{ + sint8 s8Ret; + + s8Ret = spi_read_reg(u32Addr,pu32RetVal); + + if(N_OK == s8Ret) s8Ret = M2M_SUCCESS; + else s8Ret = M2M_ERR_BUS_FAIL; + + return s8Ret; +} + +/* +* @fn nm_spi_write_reg +* @brief write register +* @param [in] u32Addr +* Register address +* @param [in] u32Val +* Value to be written to the register +* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure +* @author M. Abdelmawla +* @date 11 July 2012 +* @version 1.0 +*/ +sint8 nm_spi_write_reg(uint32 u32Addr, uint32 u32Val) +{ + sint8 s8Ret; + + s8Ret = spi_write_reg(u32Addr, u32Val); + + if(N_OK == s8Ret) s8Ret = M2M_SUCCESS; + else s8Ret = M2M_ERR_BUS_FAIL; + + return s8Ret; +} + +/* +* @fn nm_spi_read_block +* @brief Read block of data +* @param [in] u32Addr +* Start address +* @param [out] puBuf +* Pointer to a buffer used to return the read data +* @param [in] u16Sz +* Number of bytes to read. The buffer size must be >= u16Sz +* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure +* @author M. Abdelmawla +* @date 11 July 2012 +* @version 1.0 +*/ +sint8 nm_spi_read_block(uint32 u32Addr, uint8 *puBuf, uint16 u16Sz) +{ + sint8 s8Ret; + + s8Ret = nm_spi_read(u32Addr, puBuf, u16Sz); + + if(N_OK == s8Ret) s8Ret = M2M_SUCCESS; + else s8Ret = M2M_ERR_BUS_FAIL; + + return s8Ret; +} + +/* +* @fn nm_spi_write_block +* @brief Write block of data +* @param [in] u32Addr +* Start address +* @param [in] puBuf +* Pointer to the buffer holding the data to be written +* @param [in] u16Sz +* Number of bytes to write. The buffer size must be >= u16Sz +* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure +* @author M. Abdelmawla +* @date 11 July 2012 +* @version 1.0 +*/ +sint8 nm_spi_write_block(uint32 u32Addr, uint8 *puBuf, uint16 u16Sz) +{ + sint8 s8Ret; + + s8Ret = nm_spi_write(u32Addr, puBuf, u16Sz); + + if(N_OK == s8Ret) s8Ret = M2M_SUCCESS; + else s8Ret = M2M_ERR_BUS_FAIL; + + return s8Ret; +} + +#endif diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmspi.h b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmspi.h new file mode 100644 index 0000000000000..a1bd4a9dc1f11 --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmspi.h @@ -0,0 +1,132 @@ +/** + * + * \file + * + * \brief This module contains NMC1000 SPI protocol bus APIs implementation. + * + * Copyright (c) 2016-2017 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + +#ifndef _NMSPI_H_ +#define _NMSPI_H_ + +#include "common/include/nm_common.h" + +#ifdef __cplusplus + extern "C" { +#endif + +/** +* @fn nm_spi_init +* @brief Initialize the SPI +* @return ZERO in case of success and M2M_ERR_BUS_FAIL in case of failure +*/ +sint8 nm_spi_init(void); +/** +* @fn nm_spi_reset +* @brief reset the SPI +* @return ZERO in case of success and M2M_ERR_BUS_FAIL in case of failure +*/ +sint8 nm_spi_reset(void); + +/** +* @fn nm_spi_deinit +* @brief DeInitialize the SPI +* @return ZERO in case of success and M2M_ERR_BUS_FAIL in case of failure +*/ +sint8 nm_spi_deinit(void); + +/** +* @fn nm_spi_read_reg +* @brief Read register +* @param [in] u32Addr +* Register address +* @return Register value +*/ +uint32 nm_spi_read_reg(uint32 u32Addr); + +/** +* @fn nm_spi_read_reg_with_ret +* @brief Read register with error code return +* @param [in] u32Addr +* Register address +* @param [out] pu32RetVal +* Pointer to u32 variable used to return the read value +* @return ZERO in case of success and M2M_ERR_BUS_FAIL in case of failure +*/ +sint8 nm_spi_read_reg_with_ret(uint32 u32Addr, uint32* pu32RetVal); + +/** +* @fn nm_spi_write_reg +* @brief write register +* @param [in] u32Addr +* Register address +* @param [in] u32Val +* Value to be written to the register +* @return ZERO in case of success and M2M_ERR_BUS_FAIL in case of failure +*/ +sint8 nm_spi_write_reg(uint32 u32Addr, uint32 u32Val); + +/** +* @fn nm_spi_read_block +* @brief Read block of data +* @param [in] u32Addr +* Start address +* @param [out] puBuf +* Pointer to a buffer used to return the read data +* @param [in] u16Sz +* Number of bytes to read. The buffer size must be >= u16Sz +* @return ZERO in case of success and M2M_ERR_BUS_FAIL in case of failure +*/ +sint8 nm_spi_read_block(uint32 u32Addr, uint8 *puBuf, uint16 u16Sz); + +/** +* @fn nm_spi_write_block +* @brief Write block of data +* @param [in] u32Addr +* Start address +* @param [in] puBuf +* Pointer to the buffer holding the data to be written +* @param [in] u16Sz +* Number of bytes to write. The buffer size must be >= u16Sz +* @return ZERO in case of success and M2M_ERR_BUS_FAIL in case of failure +*/ +sint8 nm_spi_write_block(uint32 u32Addr, uint8 *puBuf, uint16 u16Sz); + +#ifdef __cplusplus + } +#endif + +#endif /* _NMSPI_H_ */ diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmuart.c b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmuart.c new file mode 100644 index 0000000000000..63541cf14a6a3 --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmuart.c @@ -0,0 +1,536 @@ +/** + * + * \file + * + * \brief This module contains NMC1000 UART protocol bus APIs implementation. + * + * Copyright (c) 2016 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + +#include "common/include/nm_common.h" + +#ifdef CONF_WINC_USE_UART + +#include "driver/source/nmuart.h" +#include "bus_wrapper/include/nm_bus_wrapper.h" + +#define HDR_SZ 12 + +static uint8 get_cs(uint8* b, uint8 sz){ + int i; + uint8 cs = 0; + for(i = 0; i < sz; i++) + cs ^= b[i]; + return cs; +} + +/* +* @fn nm_uart_sync_cmd +* @brief Check COM Port +* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure +* @author Dina El Sissy +* @date 13 AUG 2012 +* @version 1.0 +*/ +sint8 nm_uart_sync_cmd(void) +{ + tstrNmUartDefault strUart; + sint8 s8Ret = -1; + uint8 b [HDR_SZ+1]; + uint8 rsz; + uint8 onchip = 0; + + /*read reg*/ + b[0] = 0x12; + + rsz = 1; + strUart.pu8Buf = b; + strUart.u16Sz = 1; + + if(M2M_SUCCESS == nm_bus_ioctl(NM_BUS_IOCTL_W, &strUart)) + { + strUart.u16Sz = rsz; + if(M2M_SUCCESS != nm_bus_ioctl(NM_BUS_IOCTL_R, &strUart)) + { + s8Ret = M2M_ERR_BUS_FAIL; + } + } + else + { + M2M_ERR("failed to send cfg bytes\n"); + s8Ret = M2M_ERR_BUS_FAIL; + } + if (b[0] == 0x5a) + { + s8Ret = 0; + onchip = 1; + M2M_INFO("Built-in WINC1500 UART Found\n"); + } + else if(b[0] == 0x5b) + { + s8Ret = 0; + onchip = 0; + M2M_INFO("WINC1500 Serial Bridge Found\n"); + } + /*TODO: this should be the way we read the register since the cortus is little endian*/ + /**pu32RetVal = b[0] | ((uint32)b[1] << 8) | ((uint32)b[2] << 16) | ((uint32)b[3] << 24);*/ + if(s8Ret == M2M_SUCCESS) + s8Ret = (sint8)onchip; + return s8Ret; +} + sint8 nm_uart_read_reg_with_ret(uint32 u32Addr, uint32* pu32RetVal) +{ + tstrNmUartDefault strUart; + sint8 s8Ret = M2M_SUCCESS; + uint8 b [HDR_SZ+1]; + uint8 rsz; + + /*read reg*/ + b[0] = 0xa5; + b[1] = 0; + b[2] = 0; + b[3] = 0; + b[4] = 0; + b[5] = (uint8)(u32Addr & 0x000000ff); + b[6] = (uint8)((u32Addr & 0x0000ff00)>>8); + b[7] = (uint8)((u32Addr & 0x00ff0000)>>16); + b[8] = (uint8)((u32Addr & 0xff000000)>>24); + b[9] = 0; + b[10] = 0; + b[11] = 0; + b[12] = 0; + + b[2] = get_cs(&b[1],HDR_SZ); + + rsz = 4; + strUart.pu8Buf = b; + strUart.u16Sz = sizeof(b); + + if(M2M_SUCCESS == nm_bus_ioctl(NM_BUS_IOCTL_W, &strUart)) + { + if(!nm_bus_get_chip_type()) + { + strUart.u16Sz = 1; + if(M2M_SUCCESS != nm_bus_ioctl(NM_BUS_IOCTL_R, &strUart)) + { + s8Ret = M2M_ERR_BUS_FAIL; + } + if(b[0] == 0xAC) + { + M2M_DBG("Successfully sent the command\n"); + strUart.u16Sz = rsz; + if(M2M_SUCCESS != nm_bus_ioctl(NM_BUS_IOCTL_R, &strUart)) + { + s8Ret = M2M_ERR_BUS_FAIL; + } + } + else + { + s8Ret = M2M_ERR_BUS_FAIL; + } + } + else + { + strUart.u16Sz = rsz; + if(M2M_SUCCESS != nm_bus_ioctl(NM_BUS_IOCTL_R, &strUart)) + { + s8Ret = M2M_ERR_BUS_FAIL; + } + } + } + else + { + M2M_ERR("failed to send cfg bytes\n"); + s8Ret = M2M_ERR_BUS_FAIL; + } + /*TODO: this should be the way we read the register since the cortus is little endian*/ + /**pu32RetVal = b[0] | ((uint32)b[1] << 8) | ((uint32)b[2] << 16) | ((uint32)b[3] << 24);*/ + + *pu32RetVal = ((uint32)b[0] << 24) | ((uint32)b[1] << 16) | ((uint32)b[2] << 8) | b[3]; + + return s8Ret; +} + +/* +* @fn nm_uart_read_reg +* @brief Read register +* @param [in] u32Addr +* Register address +* @return Register value +* @author Dina El Sissy +* @date 13 AUG 2012 +* @version 1.0 +*/ +uint32 nm_uart_read_reg(uint32 u32Addr) +{ + uint32 val; + nm_uart_read_reg_with_ret(u32Addr , &val); + return val; +} + +/* +* @fn nm_uart_write_reg +* @brief write register +* @param [in] u32Addr +* Register address +* @param [in] u32Val +* Value to be written to the register +* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure +* @author Dina El Sissy +* @date 13 AUG 2012 +* @version 1.0 +*/ +sint8 nm_uart_write_reg(uint32 u32Addr, uint32 u32Val) +{ + tstrNmUartDefault strUart; + sint8 s8Ret = M2M_SUCCESS; + uint8 b[HDR_SZ+1]; + + /*write reg*/ + b[0] = 0xa5; + b[1] = 1; + b[2] = 0; + b[3] = 0; + b[4] = 0; + b[5] = (uint8)(u32Addr & 0x000000ff); + b[6] = (uint8)((u32Addr & 0x0000ff00)>>8); + b[7] = (uint8)((u32Addr & 0x00ff0000)>>16); + b[8] = (uint8)((u32Addr & 0xff000000)>>24); + b[9] = (uint8)(u32Val & 0x000000ff); + b[10] = (uint8)((u32Val & 0x0000ff00)>>8); + b[11] = (uint8)((u32Val & 0x00ff0000)>>16); + b[12] = (uint8)((u32Val & 0xff000000)>>24); + + b[2] = get_cs(&b[1],HDR_SZ); + + get_cs(&b[1],HDR_SZ); + + strUart.pu8Buf = b; + strUart.u16Sz = sizeof(b); + + if(M2M_SUCCESS != nm_bus_ioctl(NM_BUS_IOCTL_W, &strUart)) + { + M2M_ERR("write error\n"); + s8Ret = M2M_ERR_BUS_FAIL; + } + else + { + if(!nm_bus_get_chip_type()) + { + //check for the ack from the SAMD21 for the packet reception. + strUart.u16Sz = 1; + if(M2M_SUCCESS != nm_bus_ioctl(NM_BUS_IOCTL_R, &strUart)) + { + s8Ret = M2M_ERR_BUS_FAIL; + } + if(b[0] == 0xAC) + { + M2M_DBG("Successfully sent the reg write command\n"); + } + else + { + M2M_ERR("write error\n"); + s8Ret = M2M_ERR_BUS_FAIL; + } + } + } + + return s8Ret; +} + + +/** +* @fn nm_uart_read_block +* @brief Read block of data +* @param [in] u32Addr +* Start address +* @param [out] puBuf +* Pointer to a buffer used to return the read data +* @param [in] u16Sz +* Number of bytes to read. The buffer size must be >= u16Sz +* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure +* @author Dina El Sissy +* @date 13 AUG 2012 +* @version 1.0 +*/ +sint8 nm_uart_read_block(uint32 u32Addr, uint8 *pu8Buf, uint16 u16Sz) +{ + tstrNmUartDefault strUart; + sint8 s8Ret = M2M_SUCCESS; + uint8 au8Buf[HDR_SZ+1]; + + au8Buf[0] = 0xa5; + au8Buf[1] = 2; + au8Buf[2] = 0; + au8Buf[3] = (uint8)(u16Sz & 0x00ff); + au8Buf[4] = (uint8)((u16Sz & 0xff00)>>8); + au8Buf[5] = (uint8)(u32Addr & 0x000000ff); + au8Buf[6] = (uint8)((u32Addr & 0x0000ff00)>>8); + au8Buf[7] = (uint8)((u32Addr & 0x00ff0000)>>16); + au8Buf[8] = (uint8)((u32Addr & 0xff000000)>>24); + au8Buf[9] = 0; + au8Buf[10] = 0; + au8Buf[11] = 0; + au8Buf[12] = 0; + + au8Buf[2] = get_cs(&au8Buf[1],HDR_SZ); + + strUart.pu8Buf = au8Buf; + strUart.u16Sz = sizeof(au8Buf); + + if(M2M_SUCCESS != nm_bus_ioctl(NM_BUS_IOCTL_W, &strUart)) + { + M2M_ERR("write error\n"); + s8Ret = M2M_ERR_BUS_FAIL; + } + else + { + if(!nm_bus_get_chip_type()) + { + //check for the ack from the SAMD21 for the packet reception. + strUart.u16Sz = 1; + if(M2M_SUCCESS != nm_bus_ioctl(NM_BUS_IOCTL_R, &strUart)) + { + s8Ret = M2M_ERR_BUS_FAIL; + } + if(au8Buf[0] == 0xAC) + { + M2M_DBG("Successfully sent the block read command\n"); + strUart.pu8Buf = pu8Buf; + strUart.u16Sz = u16Sz; + + if(M2M_SUCCESS != nm_bus_ioctl(NM_BUS_IOCTL_R, &strUart)) + { + M2M_ERR("read error\n"); + s8Ret = M2M_ERR_BUS_FAIL; + } + } + else + { + M2M_ERR("write error (Error sending the block read command)\n"); + s8Ret = M2M_ERR_BUS_FAIL; + } + } + else + { + strUart.pu8Buf = pu8Buf; + strUart.u16Sz = u16Sz; + + if(M2M_SUCCESS != nm_bus_ioctl(NM_BUS_IOCTL_R, &strUart)) + { + M2M_ERR("read error\n"); + s8Ret = M2M_ERR_BUS_FAIL; + } + } + } + + return s8Ret; +} + +/** +* @fn nm_uart_write_block +* @brief Write block of data +* @param [in] u32Addr +* Start address +* @param [in] puBuf +* Pointer to the buffer holding the data to be written +* @param [in] u16Sz +* Number of bytes to write. The buffer size must be >= u16Sz +* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure +* @author Dina El Sissy +* @date 13 AUG 2012 +* @version 1.0 +*/ +sint8 nm_uart_write_block(uint32 u32Addr, uint8 *puBuf, uint16 u16Sz) +{ + tstrNmUartDefault strUart; + sint8 s8Ret = M2M_SUCCESS; + static uint8 au8Buf[HDR_SZ+1]; + + au8Buf[0] = 0xa5; + au8Buf[1] = 3; + au8Buf[2] = 0; + au8Buf[3] = (uint8)(u16Sz & 0x00ff); + au8Buf[4] = (uint8)((u16Sz & 0xff00)>>8); + au8Buf[5] = (uint8)(u32Addr & 0x000000ff); + au8Buf[6] = (uint8)((u32Addr & 0x0000ff00)>>8); + au8Buf[7] = (uint8)((u32Addr & 0x00ff0000)>>16); + au8Buf[8] = (uint8)((u32Addr & 0xff000000)>>24); + au8Buf[9] = 0; + au8Buf[10] = 0; + au8Buf[11] = 0; + au8Buf[12] = 0; + + au8Buf[2] = get_cs(&au8Buf[1],HDR_SZ); + + strUart.pu8Buf = au8Buf; + strUart.u16Sz = sizeof(au8Buf); + + if(M2M_SUCCESS != nm_bus_ioctl(NM_BUS_IOCTL_W, &strUart)) + { + M2M_ERR("write error\n"); + s8Ret = M2M_ERR_BUS_FAIL; + } + else + { + if(!nm_bus_get_chip_type()) + { + //check for the ack from the SAMD21 for the packet reception. + strUart.u16Sz = 1; + if(M2M_SUCCESS != nm_bus_ioctl(NM_BUS_IOCTL_R, &strUart)) + { + s8Ret = M2M_ERR_BUS_FAIL; + } + if(au8Buf[0] == 0xAC) + { + M2M_DBG("Successfully sent the block Write command\n"); + strUart.pu8Buf = puBuf; + strUart.u16Sz = u16Sz; + + if(M2M_SUCCESS != nm_bus_ioctl(NM_BUS_IOCTL_W, &strUart)) + { + M2M_ERR("write error\n"); + s8Ret = M2M_ERR_BUS_FAIL; + } + else + { + //check for the ack from the SAMD21 for the payload reception. + strUart.pu8Buf = au8Buf; + strUart.u16Sz = 1; + if(M2M_SUCCESS != nm_bus_ioctl(NM_BUS_IOCTL_R, &strUart)) + { + s8Ret = M2M_ERR_BUS_FAIL; + } + if(au8Buf[0] == 0xAC) + { + M2M_DBG("Successfully sent the data payload\n"); + } + else + { + M2M_ERR("write error\n"); + s8Ret = M2M_ERR_BUS_FAIL; + } + } + } + else + { + M2M_ERR("write error (Error sending the block write command)\n"); + s8Ret = M2M_ERR_BUS_FAIL; + } + } + else + { + strUart.pu8Buf = puBuf; + strUart.u16Sz = u16Sz; + + if(M2M_SUCCESS != nm_bus_ioctl(NM_BUS_IOCTL_W, &strUart)) + { + M2M_ERR("write error\n"); + s8Ret = M2M_ERR_BUS_FAIL; + } + } + } + return s8Ret; +} + +/** +* @fn nm_uart_reconfigure +* @brief Reconfigures the UART interface +* @param [in] ptr +* Pointer to a DWORD containing baudrate at this moment. +* @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure +* @author Viswanathan Murugesan +* @date 22 OCT 2014 +* @version 1.0 +*/ +sint8 nm_uart_reconfigure(void *ptr) +{ + tstrNmUartDefault strUart; + sint8 s8Ret = M2M_SUCCESS; + uint8 b[HDR_SZ+1]; + + /*write reg*/ + b[0] = 0xa5; + b[1] = 5; + b[2] = 0; + b[3] = 0; + b[4] = 0; + b[5] = 0; + b[6] = 0; + b[7] = 0; + b[8] = 0; + b[9] = (uint8)((*(unsigned long *)ptr) & 0x000000ff); + b[10] = (uint8)(((*(unsigned long *)ptr) & 0x0000ff00)>>8); + b[11] = (uint8)(((*(unsigned long *)ptr) & 0x00ff0000)>>16); + b[12] = (uint8)(((*(unsigned long *)ptr) & 0xff000000)>>24); + + b[2] = get_cs(&b[1],HDR_SZ); + + get_cs(&b[1],HDR_SZ); + + strUart.pu8Buf = b; + strUart.u16Sz = sizeof(b); + + if(M2M_SUCCESS != nm_bus_ioctl(NM_BUS_IOCTL_W, &strUart)) + { + M2M_ERR("write error\n"); + s8Ret = M2M_ERR_BUS_FAIL; + } + else + { + if(!nm_bus_get_chip_type()) + { + //check for the ack from the SAMD21 for the packet reception. + strUart.u16Sz = 1; + if(M2M_SUCCESS != nm_bus_ioctl(NM_BUS_IOCTL_R, &strUart)) + { + s8Ret = M2M_ERR_BUS_FAIL; + } + if(b[0] == 0xAC) + { + M2M_DBG("Successfully sent the UART reconfigure command\n"); + } + else + { + M2M_ERR("write error\n"); + s8Ret = M2M_ERR_BUS_FAIL; + } + } + } + + return s8Ret; +} +#endif +/* EOF */ diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmuart.h b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmuart.h new file mode 100644 index 0000000000000..8f07d39e1b606 --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/driver/source/nmuart.h @@ -0,0 +1,118 @@ +/** + * + * \file + * + * \brief This module contains NMC1000 UART protocol bus APIs implementation. + * + * Copyright (c) 2016 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + +#ifndef _NMUART_H_ +#define _NMUART_H_ + +#include "common/include/nm_common.h" + +/* +* @fn nm_uart_sync_cmd +* @brief Check COM Port +* @return ZERO in case of success and M2M_ERR_BUS_FAIL in case of failure +*/ +sint8 nm_uart_sync_cmd(void); +/** +* @fn nm_uart_read_reg +* @brief Read register +* @param [in] u32Addr +* Register address +* @return Register value +*/ +uint32 nm_uart_read_reg(uint32 u32Addr); + +/** +* @fn nm_uart_read_reg_with_ret +* @brief Read register with error code return +* @param [in] u32Addr +* Register address +* @param [out] pu32RetVal +* Pointer to u32 variable used to return the read value +* @return ZERO in case of success and M2M_ERR_BUS_FAIL in case of failure +*/ +sint8 nm_uart_read_reg_with_ret(uint32 u32Addr, uint32* pu32RetVal); + +/** +* @fn nm_uart_write_reg +* @brief write register +* @param [in] u32Addr +* Register address +* @param [in] u32Val +* Value to be written to the register +* @return ZERO in case of success and M2M_ERR_BUS_FAIL in case of failure +*/ +sint8 nm_uart_write_reg(uint32 u32Addr, uint32 u32Val); + +/** +* @fn nm_uart_read_block +* @brief Read block of data +* @param [in] u32Addr +* Start address +* @param [out] puBuf +* Pointer to a buffer used to return the read data +* @param [in] u16Sz +* Number of bytes to read. The buffer size must be >= u16Sz +* @return ZERO in case of success and M2M_ERR_BUS_FAIL in case of failure +*/ +sint8 nm_uart_read_block(uint32 u32Addr, uint8 *puBuf, uint16 u16Sz); + +/** +* @fn nm_uart_write_block +* @brief Write block of data +* @param [in] u32Addr +* Start address +* @param [in] puBuf +* Pointer to the buffer holding the data to be written +* @param [in] u16Sz +* Number of bytes to write. The buffer size must be >= u16Sz +* @return ZERO in case of success and M2M_ERR_BUS_FAIL in case of failure +*/ +sint8 nm_uart_write_block(uint32 u32Addr, uint8 *puBuf, uint16 u16Sz); + +/** +* @fn nm_uart_reconfigure +* @brief Reconfigures the UART interface +* @param [in] ptr +* Pointer to a DWORD containing baudrate at this moment. +* @return ZERO in case of success and M2M_ERR_BUS_FAIL in case of failure +*/ +sint8 nm_uart_reconfigure(void *ptr); +#endif /* _NMI2C_H_ */ diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/socket/include/m2m_socket_host_if.h b/ext/hal/atmel/asf/common/components/wifi/winc1500/socket/include/m2m_socket_host_if.h new file mode 100644 index 0000000000000..933ad67c8106e --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/socket/include/m2m_socket_host_if.h @@ -0,0 +1,461 @@ +/** + * + * \file + * + * \brief BSD compatible socket interface internal types. + * + * Copyright (c) 2016-2017 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ +#ifndef __M2M_SOCKET_HOST_IF_H__ +#define __M2M_SOCKET_HOST_IF_H__ + + +#ifdef __cplusplus +extern "C" { +#endif + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +INCLUDES +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ + +#ifndef _BOOT_ +#ifndef _FIRMWARE_ +#include "socket/include/socket.h" +#else +#include "m2m_types.h" +#endif +#endif + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +MACROS +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ + +/* + * HOSTNAME_MAX_SIZE is defined here and also in host_drv/socket/include/socket.h + * The two definitions must match. +*/ +#ifdef _FIRMWARE_ +#define HOSTNAME_MAX_SIZE (64) +#endif + +#define SSL_MAX_OPT_LEN HOSTNAME_MAX_SIZE + + + +#define SOCKET_CMD_INVALID 0x00 +/*!< + Invlaid Socket command value. +*/ + + +#define SOCKET_CMD_BIND 0x41 +/*!< + Socket Binding command value. +*/ + + +#define SOCKET_CMD_LISTEN 0x42 +/*!< + Socket Listening command value. +*/ + + +#define SOCKET_CMD_ACCEPT 0x43 +/*!< + Socket Accepting command value. +*/ + + +#define SOCKET_CMD_CONNECT 0x44 +/*!< + Socket Connecting command value. +*/ + + +#define SOCKET_CMD_SEND 0x45 +/*!< + Socket send command value. +*/ + + +#define SOCKET_CMD_RECV 0x46 +/*!< + Socket Recieve command value. +*/ + + +#define SOCKET_CMD_SENDTO 0x47 +/*!< + Socket sendTo command value. +*/ + + +#define SOCKET_CMD_RECVFROM 0x48 +/*!< + Socket RecieveFrom command value. +*/ + + +#define SOCKET_CMD_CLOSE 0x49 +/*!< + Socket Close command value. +*/ + + +#define SOCKET_CMD_DNS_RESOLVE 0x4A +/*!< + Socket DNS Resolve command value. +*/ + + +#define SOCKET_CMD_SSL_CONNECT 0x4B +/*!< + SSL-Socket Connect command value. +*/ + + +#define SOCKET_CMD_SSL_SEND 0x4C +/*!< + SSL-Socket Send command value. +*/ + + +#define SOCKET_CMD_SSL_RECV 0x4D +/*!< + SSL-Socket Recieve command value. +*/ + + +#define SOCKET_CMD_SSL_CLOSE 0x4E +/*!< + SSL-Socket Close command value. +*/ + + +#define SOCKET_CMD_SET_SOCKET_OPTION 0x4F +/*!< + Set Socket Option command value. +*/ + + +#define SOCKET_CMD_SSL_CREATE 0x50 +/*!< +*/ + + +#define SOCKET_CMD_SSL_SET_SOCK_OPT 0x51 +/*!< +*/ + + +#define SOCKET_CMD_PING 0x52 +/*!< +*/ + + +#define SOCKET_CMD_SSL_SET_CS_LIST 0x53 +/*!< + Recommend instead using @ref M2M_SSL_REQ_SET_CS_LIST and + associated response @ref M2M_SSL_RESP_SET_CS_LIST +*/ + + +#define SOCKET_CMD_SSL_BIND 0x54 +/*!< +*/ + + +#define SOCKET_CMD_SSL_EXP_CHECK 0x55 +/*!< +*/ + + + +#define PING_ERR_SUCCESS 0 +#define PING_ERR_DEST_UNREACH 1 +#define PING_ERR_TIMEOUT 2 + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +DATA TYPES +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ + + +/*! +* @brief +*/ +typedef struct{ + uint16 u16Family; + uint16 u16Port; + uint32 u32IPAddr; +}tstrSockAddr; + + +typedef sint8 SOCKET; +typedef tstrSockAddr tstrUIPSockAddr; + + + +/*! +@struct \ + tstrDnsReply + +@brief + DNS Reply, contains hostName and HostIP. +*/ +typedef struct{ + char acHostName[HOSTNAME_MAX_SIZE]; + uint32 u32HostIP; +}tstrDnsReply; + + +/*! +@brief +*/ +typedef struct{ + tstrSockAddr strAddr; + SOCKET sock; + uint8 u8Void; + uint16 u16SessionID; +}tstrBindCmd; + + +/*! +@brief +*/ +typedef struct{ + SOCKET sock; + sint8 s8Status; + uint16 u16SessionID; +}tstrBindReply; + + +/*! +* @brief +*/ +typedef struct{ + SOCKET sock; + uint8 u8BackLog; + uint16 u16SessionID; +}tstrListenCmd; + + +/*! +@struct \ + tstrSocketRecvMsg + +@brief Socket recv status. + + It is passed to the APPSocketEventHandler with SOCKET_MSG_RECV or SOCKET_MSG_RECVFROM message type + in a response to a user call to the recv or recvfrom. + If the received data from the remote peer is larger than the USER Buffer size (given at recv call), the data is + delivered to the user in a number of consecutive chunks according to the USER Buffer size. +*/ +typedef struct{ + SOCKET sock; + sint8 s8Status; + uint16 u16SessionID; +}tstrListenReply; + + +/*! +* @brief +*/ +typedef struct{ + tstrSockAddr strAddr; + SOCKET sListenSock; + SOCKET sConnectedSock; + uint16 u16AppDataOffset; + /*!< + In further packet send requests the host interface should put the user application + data at this offset in the allocated shared data packet. + */ +}tstrAcceptReply; + + +/*! +* @brief +*/ +typedef struct{ + tstrSockAddr strAddr; + SOCKET sock; + uint8 u8SslFlags; + uint16 u16SessionID; +}tstrConnectCmd; + + +/*! +@struct \ + tstrConnectReply + +@brief + Connect Reply, contains sock number and error value +*/ +typedef struct{ + SOCKET sock; + sint8 s8Error; + uint16 u16AppDataOffset; + /*!< + In further packet send requests the host interface should put the user application + data at this offset in the allocated shared data packet. + */ +}tstrConnectReply; + + +/*! +@brief +*/ +typedef struct{ + SOCKET sock; + uint8 u8Void; + uint16 u16DataSize; + tstrSockAddr strAddr; + uint16 u16SessionID; + uint16 u16Void; +}tstrSendCmd; + + +/*! +@struct \ + tstrSendReply + +@brief + Send Reply, contains socket number and number of sent bytes. +*/ +typedef struct{ + SOCKET sock; + uint8 u8Void; + sint16 s16SentBytes; + uint16 u16SessionID; + uint16 u16Void; +}tstrSendReply; + + +/*! +* @brief +*/ +typedef struct{ + uint32 u32Timeoutmsec; + SOCKET sock; + uint8 u8Void; + uint16 u16SessionID; +}tstrRecvCmd; + + +/*! +@struct +@brief +*/ +typedef struct{ + tstrSockAddr strRemoteAddr; + sint16 s16RecvStatus; + uint16 u16DataOffset; + SOCKET sock; + uint8 u8Void; + uint16 u16SessionID; +}tstrRecvReply; + + +/*! +* @brief +*/ +typedef struct{ + uint32 u32OptionValue; + SOCKET sock; + uint8 u8Option; + uint16 u16SessionID; +}tstrSetSocketOptCmd; + + +typedef struct{ + SOCKET sslSock; + uint8 __PAD24__[3]; +}tstrSSLSocketCreateCmd; + + +/*! +* @brief +*/ +typedef struct{ + SOCKET sock; + uint8 u8Option; + uint16 u16SessionID; + uint32 u32OptLen; + uint8 au8OptVal[SSL_MAX_OPT_LEN]; +}tstrSSLSetSockOptCmd; + + +/*! +*/ +typedef struct{ + uint32 u32DestIPAddr; + uint32 u32CmdPrivate; + uint16 u16PingCount; + uint8 u8TTL; + uint8 __PAD8__; +}tstrPingCmd; + + +typedef struct{ + uint32 u32IPAddr; + uint32 u32CmdPrivate; + uint32 u32RTT; + uint16 u16Success; + uint16 u16Fail; + uint8 u8ErrorCode; + uint8 __PAD24__[3]; +}tstrPingReply; + + +/*! +@struct\ + tstrSslCertExpSettings + +@brief SSL Certificate Expiry Validation Settings + +@sa tenuSslCertExpSettings +*/ +typedef struct{ + uint32 u32CertExpValidationOpt; + /*!< + See @tenuSslCertExpSettings for possible values. + */ +}tstrSslCertExpSettings; + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __M2M_SOCKET_HOST_IF_H__ */ diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/socket/include/socket.h b/ext/hal/atmel/asf/common/components/wifi/winc1500/socket/include/socket.h new file mode 100644 index 0000000000000..5789627e98f79 --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/socket/include/socket.h @@ -0,0 +1,2061 @@ +/** + * + * \file + * + * \brief WINC BSD compatible Socket Interface. + * + * Copyright (c) 2016-2017 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + +#ifndef __SOCKET_H__ +#define __SOCKET_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup SocketHeader Socket + * BSD compatible socket interface beftween the host layer and the network + * protocol stacks in the firmware. + * These functions are used by the host application to send or receive + * packets and to do other socket operations. + */ + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +INCLUDES +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ + +#include "common/include/nm_common.h" +#include "driver/include/m2m_types.h" + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +MACROS +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ +/** + * @defgroup SocketDefines Defines + * @ingroup SocketHeader + */ + +/** @defgroup IPDefines TCP/IP Defines + * @ingroup SocketDefines + * The following list of macros are used to define constants used throughout the socket layer. + * @{ + */ + +/* + * HOSTNAME_MAX_SIZE is defined here and also in host_drv/socket/include/m2m_socket_host_if.h + * The two definitions must match. +*/ +#define HOSTNAME_MAX_SIZE 64 +/*!< + Maximum allowed size for a host domain name passed to the function gethostbyname @ref gethostbyname. + command value. Used with the setsockopt function. + +*/ + +#define SOCKET_BUFFER_MAX_LENGTH 1400 +/*!< + Maximum allowed size for a socket data buffer. Used with @ref send socket + function to ensure that the buffer sent is within the allowed range. +*/ + +#define AF_INET 2 +/*!< + The AF_INET is the address family used for IPv4. An IPv4 transport address is specified with the @ref sockaddr_in structure. + (It is the only supported type for the current implementation.) +*/ + + +#define SOCK_STREAM 1 +/*!< + One of the IPv4 supported socket types for reliable connection-oriented stream connection. + Passed to the @ref socket function for the socket creation operation. +*/ + +#define SOCK_DGRAM 2 +/*!< + One of the IPv4 supported socket types for unreliable connectionless datagram connection. + Passed to the @ref socket function for the socket creation operation. +*/ + + +#define SOCKET_FLAGS_SSL 0x01 +/*!< + This flag shall be passed to the socket API for SSL session. +*/ + +#define TCP_SOCK_MAX (7) +/*!< + Maximum number of simultaneous TCP sockets. +*/ + +#define UDP_SOCK_MAX 4 +/*!< + Maximum number of simultaneous UDP sockets. +*/ + +#define MAX_SOCKET (TCP_SOCK_MAX + UDP_SOCK_MAX) +/*!< + Maximum number of Sockets. +*/ + +#define SOL_SOCKET 1 +/*!< + Socket option. + Used with the @ref setsockopt function +*/ + +#define SOL_SSL_SOCKET 2 +/*!< + SSL Socket option level. + Used with the @ref setsockopt function +*/ + +#define SO_SET_UDP_SEND_CALLBACK 0x00 +/*!< + Socket option used by the application to enable/disable + the use of UDP send callbacks. + Used with the @ref setsockopt function. +*/ + +#define IP_ADD_MEMBERSHIP 0x01 +/*!< + Set Socket Option Add Membership command value (to join a multicast group). + Used with the @ref setsockopt function. +*/ + + +#define IP_DROP_MEMBERSHIP 0x02 +/*!< + Set Socket Option Drop Membership command value (to leave a multicast group). + Used with the @ref setsockopt function. +*/ + //@} + + + +/** + * @defgroup TLSDefines TLS Defines + * @ingroup SocketDefines + */ + + + +/** @defgroup SSLSocketOptions TLS Socket Options + * @ingroup TLSDefines + * The following list of macros are used to define SSL Socket options. + * @{ + * @sa setsockopt + */ + +#define SO_SSL_BYPASS_X509_VERIF 0x01 +/*!< + Allow an opened SSL socket to bypass the X509 certificate + verification process. + It is highly required NOT to use this socket option in production + software applications. It is supported for debugging and testing + purposes. + The option value should be casted to int type and it is handled + as a boolean flag. +*/ + + +#define SO_SSL_SNI 0x02 +/*!< + Set the Server Name Indicator (SNI) for an SSL socket. The + SNI is a NULL terminated string containing the server name + associated with the connection. It must not exceed the size + of HOSTNAME_MAX_SIZE. +*/ + + +#define SO_SSL_ENABLE_SESSION_CACHING 0x03 +/*!< + This option allow the TLS to cache the session information for fast + TLS session establishment in future connections using the + TLS Protocol session resume features. +*/ + + +#define SO_SSL_ENABLE_SNI_VALIDATION 0x04 +/*!< + Enable SNI validation against the server's certificate subject + common name. If there is no SNI provided (via the SO_SSL_SNI + option), setting this option does nothing. +*/ + + +//@} + + + +/** @defgroup LegacySSLCipherSuite Legacy names for TLS Cipher Suite IDs + * @ingroup TLSDefines + * The following list of macros MUST NOT be used. Instead use the new names under SSLCipherSuiteID + * @sa sslSetActiveCipherSuites + * @{ + */ + +#define SSL_ENABLE_RSA_SHA_SUITES 0x01 +/*!< + Enable RSA Hmac_SHA based Cipher suites. For example, + TLS_RSA_WITH_AES_128_CBC_SHA +*/ + + +#define SSL_ENABLE_RSA_SHA256_SUITES 0x02 +/*!< + Enable RSA Hmac_SHA256 based Cipher suites. For example, + TLS_RSA_WITH_AES_128_CBC_SHA256 +*/ + + +#define SSL_ENABLE_DHE_SHA_SUITES 0x04 +/*!< + Enable DHE Hmac_SHA based Cipher suites. For example, + TLS_DHE_RSA_WITH_AES_128_CBC_SHA +*/ + + +#define SSL_ENABLE_DHE_SHA256_SUITES 0x08 +/*!< + Enable DHE Hmac_SHA256 based Cipher suites. For example, + TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 +*/ + + +#define SSL_ENABLE_RSA_GCM_SUITES 0x10 +/*!< + Enable RSA AEAD based Cipher suites. For example, + TLS_RSA_WITH_AES_128_GCM_SHA256 +*/ + + +#define SSL_ENABLE_DHE_GCM_SUITES 0x20 +/*!< + Enable DHE AEAD based Cipher suites. For example, + TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 +*/ + + +#define SSL_ENABLE_ALL_SUITES 0x0000003F +/*!< + Enable all possible supported cipher suites. +*/ + +//@} + + + +/** @defgroup SSLCipherSuiteID TLS Cipher Suite IDs + * @ingroup TLSDefines + * The following list of macros defined the list of supported TLS Cipher suites. + * Each MACRO defines a single Cipher suite. + * @sa m2m_ssl_set_active_ciphersuites + * @{ + */ + +#define SSL_CIPHER_RSA_WITH_AES_128_CBC_SHA NBIT0 +#define SSL_CIPHER_RSA_WITH_AES_128_CBC_SHA256 NBIT1 +#define SSL_CIPHER_DHE_RSA_WITH_AES_128_CBC_SHA NBIT2 +#define SSL_CIPHER_DHE_RSA_WITH_AES_128_CBC_SHA256 NBIT3 +#define SSL_CIPHER_RSA_WITH_AES_128_GCM_SHA256 NBIT4 +#define SSL_CIPHER_DHE_RSA_WITH_AES_128_GCM_SHA256 NBIT5 +#define SSL_CIPHER_RSA_WITH_AES_256_CBC_SHA NBIT6 +#define SSL_CIPHER_RSA_WITH_AES_256_CBC_SHA256 NBIT7 +#define SSL_CIPHER_DHE_RSA_WITH_AES_256_CBC_SHA NBIT8 +#define SSL_CIPHER_DHE_RSA_WITH_AES_256_CBC_SHA256 NBIT9 +#define SSL_CIPHER_ECDHE_RSA_WITH_AES_128_CBC_SHA NBIT10 +#define SSL_CIPHER_ECDHE_RSA_WITH_AES_256_CBC_SHA NBIT11 +#define SSL_CIPHER_ECDHE_RSA_WITH_AES_128_CBC_SHA256 NBIT12 +#define SSL_CIPHER_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 NBIT13 +#define SSL_CIPHER_ECDHE_RSA_WITH_AES_128_GCM_SHA256 NBIT14 +#define SSL_CIPHER_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 NBIT15 + + + +#define SSL_ECC_ONLY_CIPHERS \ +(\ + SSL_CIPHER_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | \ + SSL_CIPHER_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 \ +) +/*!< + All ciphers that use ECC crypto only. This execuldes ciphers that use RSA. They use ECDSA instead. + These ciphers are turned off by default at startup. + The application may enable them if it has an ECC math engine (like ATECC508). +*/ +#define SSL_ECC_ALL_CIPHERS \ +(\ + SSL_CIPHER_ECDHE_RSA_WITH_AES_128_CBC_SHA | \ + SSL_CIPHER_ECDHE_RSA_WITH_AES_128_CBC_SHA256 | \ + SSL_CIPHER_ECDHE_RSA_WITH_AES_128_GCM_SHA256 | \ + SSL_CIPHER_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | \ + SSL_CIPHER_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 \ +) +/*!< + All supported ECC Ciphers including those ciphers that depend on RSA and ECC. + These ciphers are turned off by default at startup. + The application may enable them if it has an ECC math engine (like ATECC508). +*/ + +#define SSL_NON_ECC_CIPHERS_AES_128 \ +(\ + SSL_CIPHER_RSA_WITH_AES_128_CBC_SHA | \ + SSL_CIPHER_RSA_WITH_AES_128_CBC_SHA256 | \ + SSL_CIPHER_DHE_RSA_WITH_AES_128_CBC_SHA | \ + SSL_CIPHER_DHE_RSA_WITH_AES_128_CBC_SHA256 | \ + SSL_CIPHER_RSA_WITH_AES_128_GCM_SHA256 | \ + SSL_CIPHER_DHE_RSA_WITH_AES_128_GCM_SHA256 \ +) +/*!< + All supported AES-128 Ciphers (ECC ciphers are not counted). This is the default active group after startup. +*/ + + +#define SSL_ECC_CIPHERS_AES_256 \ +(\ + SSL_CIPHER_ECDHE_RSA_WITH_AES_256_CBC_SHA \ +) +/*!< + ECC AES-256 supported ciphers. +*/ + + +#define SSL_NON_ECC_CIPHERS_AES_256 \ +(\ + SSL_CIPHER_RSA_WITH_AES_256_CBC_SHA | \ + SSL_CIPHER_RSA_WITH_AES_256_CBC_SHA256 | \ + SSL_CIPHER_DHE_RSA_WITH_AES_256_CBC_SHA | \ + SSL_CIPHER_DHE_RSA_WITH_AES_256_CBC_SHA256 \ +) +/*!< + AES-256 Ciphers. + This group is disabled by default at startup because the WINC1500 HW Accelerator + supports only AES-128. If the application needs to force AES-256 cipher support, + it could enable them (or any of them) explicitly by calling sslSetActiveCipherSuites. +*/ + + +#define SSL_CIPHER_ALL \ +(\ + SSL_CIPHER_RSA_WITH_AES_128_CBC_SHA | \ + SSL_CIPHER_RSA_WITH_AES_128_CBC_SHA256 | \ + SSL_CIPHER_DHE_RSA_WITH_AES_128_CBC_SHA | \ + SSL_CIPHER_DHE_RSA_WITH_AES_128_CBC_SHA256 | \ + SSL_CIPHER_RSA_WITH_AES_128_GCM_SHA256 | \ + SSL_CIPHER_DHE_RSA_WITH_AES_128_GCM_SHA256 | \ + SSL_CIPHER_RSA_WITH_AES_256_CBC_SHA | \ + SSL_CIPHER_RSA_WITH_AES_256_CBC_SHA256 | \ + SSL_CIPHER_DHE_RSA_WITH_AES_256_CBC_SHA | \ + SSL_CIPHER_DHE_RSA_WITH_AES_256_CBC_SHA256 | \ + SSL_CIPHER_ECDHE_RSA_WITH_AES_128_CBC_SHA | \ + SSL_CIPHER_ECDHE_RSA_WITH_AES_128_CBC_SHA256 | \ + SSL_CIPHER_ECDHE_RSA_WITH_AES_128_GCM_SHA256 | \ + SSL_CIPHER_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | \ + SSL_CIPHER_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 | \ + SSL_CIPHER_ECDHE_RSA_WITH_AES_256_CBC_SHA \ +) +/*!< + Turn On All TLS Ciphers. +*/ + + + //@} + + + + +/************** +Socket Errors +**************/ +/**@defgroup SocketErrorCode Error Codes + * @ingroup SocketHeader + * The following list of macros are used to define the possible error codes returned as a result of a call to a socket function. + * Errors are listed in numerical order with the error macro name. + * @{ + */ +#define SOCK_ERR_NO_ERROR 0 +/*!< + Successful socket operation +*/ + + +#define SOCK_ERR_INVALID_ADDRESS -1 +/*!< + Socket address is invalid. The socket operation cannot be completed successfully without specifying a specific address + For example: bind is called without specifying a port number +*/ + + +#define SOCK_ERR_ADDR_ALREADY_IN_USE -2 +/*!< + Socket operation cannot bind on the given address. With socket operations, only one IP address per socket is permitted. + Any attempt for a new socket to bind with an IP address already bound to another open socket, + will return the following error code. States that bind operation failed. +*/ + + +#define SOCK_ERR_MAX_TCP_SOCK -3 +/*!< + Exceeded the maximum number of TCP sockets. A maximum number of TCP sockets opened simultaneously is defined through TCP_SOCK_MAX. + It is not permitted to exceed that number at socket creation. Identifies that @ref socket operation failed. +*/ + + +#define SOCK_ERR_MAX_UDP_SOCK -4 +/*!< + Exceeded the maximum number of UDP sockets. A maximum number of UDP sockets opened simultaneously is defined through UDP_SOCK_MAX. + It is not permitted to exceed that number at socket creation. Identifies that @ref socket operation failed +*/ + + +#define SOCK_ERR_INVALID_ARG -6 +/*!< + An invalid argument is passed to a function. +*/ + + +#define SOCK_ERR_MAX_LISTEN_SOCK -7 +/*!< + Exceeded the maximum number of TCP passive listening sockets. + Identifies Identifies that @ref listen operation failed. +*/ + + +#define SOCK_ERR_INVALID -9 +/*!< + The requested socket operation is not valid in the + current socket state. + For example: @ref accept is called on a TCP socket before @ref bind or @ref listen. +*/ + + +#define SOCK_ERR_ADDR_IS_REQUIRED -11 +/*!< + Destination address is required. Failure to provide the socket address required for the socket operation to be completed. + It is generated as an error to the @ref sendto function when the address required to send the data to is not known. +*/ + + +#define SOCK_ERR_CONN_ABORTED -12 +/*!< + The socket is closed by the peer. The local socket is + closed also. +*/ + + +#define SOCK_ERR_TIMEOUT -13 +/*!< + The socket pending operation has Timedout. +*/ + + +#define SOCK_ERR_BUFFER_FULL -14 +/*!< + No buffer space available to be used for the requested socket operation. +*/ + +#ifdef _NM_BSP_BIG_END + +#define _htonl(m) (m) +#define _htons(A) (A) + +#else + +#define _htonl(m) \ + (uint32)(((uint32)(m << 24)) | ((uint32)((m & 0x0000FF00) << 8)) | ((uint32)((m & 0x00FF0000) >> 8)) | ((uint32)(m >> 24))) +/*!< + Convert a 4-byte integer from the host representation to the Network byte order representation. +*/ + + +#define _htons(A) (uint16)((((uint16) (A)) << 8) | (((uint16) (A)) >> 8)) +/*!< + Convert a 2-byte integer (short) from the host representation to the Network byte order representation. +*/ + + +#endif + + +#define _ntohl _htonl +/*!< + Convert a 4-byte integer from the Network byte order representation to the host representation . +*/ + + +#define _ntohs _htons +/*!< + Convert a 2-byte integer from the Network byte order representation to the host representation . +*/ + //@} + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +DATA TYPES +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ +/** @defgroup SocketEnums DataTypes + * @ingroup SocketHeader + * Specific Enumeration-typedefs used for socket operations + * @{ */ + +/*! +@typedef \ + SOCKET + +@brief + Definition for socket handler data type. + Socket ID,used with all socket operations to uniquely identify the socket handler. + Such an ID is uniquely assigned at socket creation when calling @ref socket operation. +*/ +typedef sint8 SOCKET; + + + +/*! +@struct \ + in_addr + +@brief + IPv4 address representation. + + This structure is used as a placeholder for IPV4 address in other structures. +@see + sockaddr_in +*/ +typedef struct{ + uint32 s_addr; + /*!< + Network Byte Order representation of the IPv4 address. For example, + the address "192.168.0.10" is represented as 0x0A00A8C0. + */ +}in_addr; + + +/*! +@struct \ + sockaddr + +@brief + Generic socket address structure. + +@see + sockaddr_in +*/ +struct sockaddr{ + uint16 sa_family; + /*!< +Socket address family. + */ + uint8 sa_data[14]; + /*!< + Maximum size of all the different socket address structures. + */ +}; + + +/*! +@struct \ + sockaddr_in + +@brief + Socket address structure for IPV4 addresses. Used to specify socket address information to which to connect to. + Can be cast to @ref sockaddr structure. +*/ +struct sockaddr_in{ + uint16 sin_family; + /*!< + Specifies the address family(AF). + Members of AF_INET address family are IPv4 addresses. + Hence,the only supported value for this is AF_INET. + */ + uint16 sin_port; + /*!< + Port number of the socket. + Network sockets are identified by a pair of IP addresses and port number. + It must be set in the Network Byte Order format , @ref _htons (e.g. _htons(80)). + Can NOT have zero value. + */ + in_addr sin_addr; + /*!< + IP Address of the socket. + The IP address is of type @ref in_addr structure. + Can be set to "0" to accept any IP address for server operation. non zero otherwise. + */ + uint8 sin_zero[8]; + /*!< + Padding to make structure the same size as @ref sockaddr. + */ +}; + //@} +/**@defgroup AsyncCalback Asynchronous Events + * @ingroup SocketEnums + * Specific Enumeration used for asynchronous operations + * @{ */ +/*! +@enum \ + tenuSocketCallbackMsgType + +@brief + Asynchronous APIs, make use of callback functions, in-order to return back the results once the corresponding socket operation is completed. + Hence resuming the normal execution of the application code while the socket operation returns the results. + Callback functions expect event messages to be passed in, in-order to identify the operation they're returning the results for. + The following enum identifies the type of events that are received in the callback function. + + Application Use: + In order for application developers to handle the pending events from the network controller through the callback functions. + A function call must be made to the function @ref m2m_wifi_handle_events at least once for each socket operation. + +@see + bind + listen + accept + connect + send + recv + +*/ +typedef enum{ + SOCKET_MSG_BIND = 1, + /*!< + Bind socket event. + */ + SOCKET_MSG_LISTEN, + /*!< + Listen socket event. + */ + SOCKET_MSG_DNS_RESOLVE, + /*!< + DNS Resolution event. + */ + SOCKET_MSG_ACCEPT, + /*!< + Accept socket event. + */ + SOCKET_MSG_CONNECT, + /*!< + Connect socket event. + */ + SOCKET_MSG_RECV, + /*!< + Receive socket event. + */ + SOCKET_MSG_SEND, + /*!< + Send socket event. + */ + SOCKET_MSG_SENDTO, + /*!< + sendto socket event. + */ + SOCKET_MSG_RECVFROM + /*!< + Recvfrom socket event. + */ +}tenuSocketCallbackMsgType; + + +/*! +@struct \ + tstrSocketBindMsg + +@brief Socket bind status. + + An asynchronous call to the @ref bind socket operation, returns information through this structure in response. + This structure together with the event @ref SOCKET_MSG_BIND are passed in paramters to the callback function. +@see + bind + +*/ +typedef struct{ + sint8 status; + /*!< + The result of the bind operation. + Holding a value of ZERO for a successful bind or otherwise a negative + error code corresponding to the type of error. + */ +}tstrSocketBindMsg; + + +/*! +@struct \ + tstrSocketListenMsg + +@brief Socket listen status. + + Socket listen information is returned through this structure in response to the asynchronous call to the @ref listen function. + This structure together with the event @ref SOCKET_MSG_LISTEN are passed-in parameters to the callback function. +@see + listen +*/ +typedef struct{ + sint8 status; + /*!< + Holding a value of ZERO for a successful listen or otherwise a negative + error code corresponding to the type of error. + */ +}tstrSocketListenMsg; + + + +/*! +@struct \ + tstrSocketAcceptMsg + +@brief Socket accept status. + + Socket accept information is returned through this structure in response to the asynchronous call to the @ref accept function. + This structure together with the event @ref SOCKET_MSG_ACCEPT are passed-in parameters to the callback function. +*/ +typedef struct{ + SOCKET sock; + /*!< + On a successful @ref accept operation, the return information is the socket ID for the accepted connection with the remote peer. + Otherwise a negative error code is returned to indicate failure of the accept operation. + */ + struct sockaddr_in strAddr; + /*!< + Socket address structure for the remote peer. + */ +}tstrSocketAcceptMsg; + + +/*! +@struct \ + tstrSocketConnectMsg + +@brief Socket connect status. + + Socket connect information is returned through this structure in response to the asynchronous call to the @ref connect socket function. + This structure together with the event @ref SOCKET_MSG_CONNECT are passed-in parameters to the callback function. +*/ +typedef struct{ + SOCKET sock; + /*!< + Socket ID referring to the socket passed to the connect function call. + */ + sint8 s8Error; + /*!< + Connect error code. + Holding a value of ZERO for a successful connect or otherwise a negative + error code corresponding to the type of error. + */ +}tstrSocketConnectMsg; + + +/*! +@struct \ + tstrSocketRecvMsg + +@brief Socket recv status. + + Socket receive information is returned through this structure in response to the asynchronous call to the recv or recvfrom socket functions. + This structure together with the events @ref SOCKET_MSG_RECV or @ref SOCKET_MSG_RECVFROM are passed-in parameters to the callback function. +@remark + In case the received data from the remote peer is larger than the USER buffer size defined during the asynchronous call to the @ref recv function, the data is + delivered to the user in a number of consecutive chunks according to the USER Buffer size. + a negative or zero buffer size indicates an error with the following code: + @ref SOCK_ERR_NO_ERROR : Socket connection closed + @ref SOCK_ERR_CONN_ABORTED : Socket connection aborted + @SOCK_ERR_TIMEOUT : Socket receive timed out +*/ +typedef struct{ + uint8 *pu8Buffer; + /*!< + Pointer to the USER buffer (passed to @ref recv and @ref recvfrom function) containing the received data chunk. + */ + sint16 s16BufferSize; + /*!< + The received data chunk size. + Holds a negative value if there is a receive error or ZERO on success upon reception of close socket message. + */ + uint16 u16RemainingSize; + /*!< + The number of bytes remaining in the current @ref recv operation. + */ + struct sockaddr_in strRemoteAddr; + /*!< + Socket address structure for the remote peer. It is valid for @ref SOCKET_MSG_RECVFROM event. + */ +}tstrSocketRecvMsg; + + +/*! +@typedef \ + tpfAppSocketCb + +@brief + The main socket application callback function. Applications register their main socket application callback through this function by calling @ref registerSocketCallback. + In response to events received, the following callback function is called to handle the corresponding asynchronous function called. Example: @ref bind, @ref connect,...etc. + +@param [in] sock + Socket ID for the callback. + + The socket callback function is called whenever a new event is recived in response + to socket operations. + +@param [in] u8Msg + Socket event type. Possible values are: + - @ref SOCKET_MSG_BIND + - @ref SOCKET_MSG_LISTEN + - @ref SOCKET_MSG_ACCEPT + - @ref SOCKET_MSG_CONNECT + - @ref SOCKET_MSG_RECV + - @ref SOCKET_MSG_SEND + - @ref SOCKET_MSG_SENDTO + - @ref SOCKET_MSG_RECVFROM + +@param [in] pvMsg + Pointer to message structure. Existing types are: + - tstrSocketBindMsg + - tstrSocketListenMsg + - tstrSocketAcceptMsg + - tstrSocketConnectMsg + - tstrSocketRecvMsg + +@see + tenuSocketCallbackMsgType + tstrSocketRecvMsg + tstrSocketConnectMsg + tstrSocketAcceptMsg + tstrSocketListenMsg + tstrSocketBindMsg +*/ +typedef void (*tpfAppSocketCb) (SOCKET sock, uint8 u8Msg, void * pvMsg); + + +/*! +@typedef \ + tpfAppResolveCb + +@brief + DNS resolution callback function. + Applications requiring DNS resolution should register their callback through this function by calling @ref registerSocketCallback. + The following callback is triggered in response to asynchronous call to the @ref gethostbyname function (DNS Resolution callback). + +@param [in] pu8DomainName + Domain name of the host. + +@param [in] u32ServerIP + Server IPv4 address encoded in NW byte order format. If it is Zero, then the DNS resolution failed. +*/ +typedef void (*tpfAppResolveCb) (uint8* pu8DomainName, uint32 u32ServerIP); + +/*! +@typedef \ + tpfPingCb + +@brief PING Callback + + The function delivers the ping statistics for the sent ping triggered by calling + m2m_ping_req. + +@param [in] u32IPAddr + Destination IP. + +@param [in] u32RTT + Round Trip Time. + +@param [in] u8ErrorCode + Ping error code. It may be one of: + - PING_ERR_SUCCESS + - PING_ERR_DEST_UNREACH + - PING_ERR_TIMEOUT +*/ +typedef void (*tpfPingCb)(uint32 u32IPAddr, uint32 u32RTT, uint8 u8ErrorCode); + + /**@}*/ +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +FUNCTION PROTOTYPES +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ +/** \defgroup SocketAPI Function + * @ingroup SocketHeader + */ + +/** @defgroup SocketInitalizationFn socketInit + * @ingroup SocketAPI + * The function performs the necessary initializations for the socket library through the following steps: + - A check made by the global variable gbSocketInit, ensuring that initialization for sockets is performed only once, + in-order to prevent reseting the socket instances already created in the global socket array (gastrSockets). + - Zero initializations to the global socket array (gastrSockets), which holds the list of TCP sockets. + - Registers the socket (Host Interface)hif callback function through the call to the hif_register_cb function. + This facilitates handling all of the socket related functions received through interrupts from the firmware. + + */ + /**@{*/ +/*! +@fn \ + NMI_API void socketInit(void); + +@param [in] void + +@return void + +@remarks + This initialization function must be invoked before any socket operation is performed. + No error codes from this initialization function since the socket array is statically allocated based in the maximum number of + sockets @ref MAX_SOCKET based on the systems capability. +\section Example +This example demonstrates the use of the socketinit for socket initialization for an mqtt chat application. + \code + tstrWifiInitParam param; + int8_t ret; + char topic[strlen(MAIN_CHAT_TOPIC) + MAIN_CHAT_USER_NAME_SIZE + 1]; + + //Initialize the board. + system_init(); + + //Initialize the UART console. + configure_console(); + + // Initialize the BSP. + nm_bsp_init(); + + ---------- + + // Initialize socket interface. + socketInit(); + registerSocketCallback(socket_event_handler, socket_resolve_handler); + + // Connect to router. + m2m_wifi_connect((char *)MAIN_WLAN_SSID, sizeof(MAIN_WLAN_SSID), + MAIN_WLAN_AUTH, (char *)MAIN_WLAN_PSK, M2M_WIFI_CH_ALL); + +\endcode +*/ +NMI_API void socketInit(void); + + +/*! +@fn \ + NMI_API void socketDeinit(void); + +@brief Socket Layer De-initialization + + The function performs the necessary cleanup for the socket library static data + It must be invoked as the last any socket operation is performed on any active sockets. +*/ +NMI_API void socketDeinit(void); + + +/** @} */ +/** @defgroup SocketCallbackFn registerSocketCallback + * @ingroup SocketAPI + Register two callback functions one for asynchronous socket events and the other one for DNS callback registering function. + The registered callback functions are used to retrieve information in response to the asynchronous socket functions called. + */ + /**@{*/ + + +/*! +@fn \ + NMI_API void registerSocketCallback(tpfAppSocketCb socket_cb, tpfAppResolveCb resolve_cb); + +@param [in] tpfAppSocketCb + Assignment of callback function to the global callback @ref tpfAppSocketCb gpfAppSocketCb. Delivers + socket messages to the host application. In response to the asynchronous function calls, such as @ref bind + @ref listen @ref accept @ref connect + +@param [in] tpfAppResolveCb + Assignment of callback function to the global callback @ref tpfAppResolveCb gpfAppResolveCb. + Used for DNS resolving functionalities. The DNS resolving technique is determined by the application + registering the callback. + NULL is assigned when, DNS resolution is not required. + +@return void +@remarks + If any of the socket functionalities is not to be used, NULL is passed in as a parameter. + It must be invoked after socketinit and before other socket layer operations. + +\section Example + This example demonstrates the use of the registerSocketCallback to register a socket callback function with DNS resolution CB set to null + for a simple UDP server example. + \code + tstrWifiInitParam param; + int8_t ret; + struct sockaddr_in addr; + + // Initialize the board + system_init(); + + //Initialize the UART console. + configure_console(); + + // Initialize the BSP. + nm_bsp_init(); + + // Initialize socket address structure. + addr.sin_family = AF_INET; + addr.sin_port = _htons(MAIN_WIFI_M2M_SERVER_PORT); + addr.sin_addr.s_addr = _htonl(MAIN_WIFI_M2M_SERVER_IP); + + // Initialize Wi-Fi parameters structure. + memset((uint8_t *)¶m, 0, sizeof(tstrWifiInitParam)); + + // Initialize Wi-Fi driver with data and status callbacks. + param.pfAppWifiCb = wifi_cb; + ret = m2m_wifi_init(¶m); + if (M2M_SUCCESS != ret) { + printf("main: m2m_wifi_init call error!(%d)\r\n", ret); + while (1) { + } + } + + // Initialize socket module + socketInit(); + registerSocketCallback(socket_cb, NULL); + + // Connect to router. + m2m_wifi_connect((char *)MAIN_WLAN_SSID, sizeof(MAIN_WLAN_SSID), MAIN_WLAN_AUTH, (char *)MAIN_WLAN_PSK, M2M_WIFI_CH_ALL); + \endcode +*/ +NMI_API void registerSocketCallback(tpfAppSocketCb socket_cb, tpfAppResolveCb resolve_cb); + + +/** @} */ + +/** @defgroup SocketFn socket + * @ingroup SocketAPI + * Synchronous socket allocation function based on the specified socket type. Created sockets are non-blocking and their possible types are either TCP or a UDP sockets. + * The maximum allowed number of TCP sockets is @ref TCP_SOCK_MAX sockets while the maximum number of UDP sockets that can be created simultaneously is @ref UDP_SOCK_MAX sockets. + * +*/ + /**@{*/ +/*! +@fn \ + NMI_API SOCKET socket(uint16 u16Domain, uint8 u8Type, uint8 u8Flags); + + +@param [in] u16Domain + Socket family. The only allowed value is AF_INET (IPv4.0) for TCP/UDP sockets. + +@param [in] u8Type + Socket type. Allowed values are: + - [SOCK_STREAM](@ref SOCK_STREAM) + - [SOCK_DGRAM](@ref SOCK_DGRAM) + +@param [in] u8Flags + Used to specify the socket creation flags. It shall be set to zero for normal TCP/UDP sockets. + It could be @ref SOCKET_FLAGS_SSL if the socket is used for SSL session. The use of the flag + @ref SOCKET_FLAGS_SSL has no meaning in case of UDP sockets. + +@pre + The @ref socketInit function must be called once at the beginning of the application to initialize the socket handler. + before any call to the socket function can be made. + +@see + connect + bind + listen + accept + recv + recvfrom + send + sendto + close + setsockopt + getsockopt + +@return + On successful socket creation, a non-blocking socket type is created and a socket ID is returned + In case of failure the function returns a negative value, identifying one of the socket error codes defined. + For example: @ref SOCK_ERR_INVALID for invalid argument or + @ref SOCK_ERR_MAX_TCP_SOCK if the number of TCP allocated sockets exceeds the number of available sockets. + +@remarks + The socket function must be called a priori to any other related socket functions "e.g. send, recv, close ..etc" +\section Example + This example demonstrates the use of the socket function to allocate the socket, returning the socket handler to be used for other +socket operations. Socket creation is dependent on the socket type. +\subsection sub1 UDP example +@code + SOCKET UdpServerSocket = -1; + + UdpServerSocket = socket(AF_INET, SOCK_DGRAM, 0); + +@endcode +\subsection sub2 TCP example +@code + static SOCKET tcp_client_socket = -1; + + tcp_client_socket = socket(AF_INET, SOCK_STREAM, 0)); +@endcode +\subsection sub3 SSL example +@code +static SOCKET ssl_socket = -1; + +ssl_socket = socket(AF_INET, SOCK_STREAM, SOCK_FLAGS_SSL)); +@endcode +*/ +NMI_API SOCKET socket(uint16 u16Domain, uint8 u8Type, uint8 u8Flags); + + +/** @} */ +/** @defgroup BindFn bind + * @ingroup SocketAPI +* Asynchronous bind function associates the provided address and local port to the socket. +* The function can be used with both TCP and UDP sockets it's mandatory to call the @ref bind function before starting any UDP or TCP server operation. +* Upon socket bind completion, the application will receive a @ref SOCKET_MSG_BIND message in the socket callback. +*/ + /**@{*/ +/*! +\fn \ + NMI_API sint8 bind(SOCKET sock, struct sockaddr *pstrAddr, uint8 u8AddrLen); + + +@param [in] sock + Socket ID, must hold a non negative value. + A negative value will return a socket error @ref SOCK_ERR_INVALID_ARG. Indicating that an invalid argument is passed in. + +@param [in] pstrAddr + Pointer to socket address structure "sockaddr_in" + [sockaddr_in](@ref sockaddr_in) + + +@param [in] u8AddrLen + Size of the given socket address structure in bytes. + +@pre + The socket function must be called to allocate a socket before passing the socket ID to the bind function. + +@see + socket + connect + listen + accept + recv + recvfrom + send + sendto + +@return + The function returns ZERO for successful operations and a negative value otherwise. + The possible error values are: + - [SOCK_ERR_NO_ERROR](@ref SOCK_ERR_NO_ERROR) + Indicating that the operation was successful. + + - [SOCK_ERR_INVALID_ARG](@ref SOCK_ERR_INVALID_ARG) + Indicating passing invalid arguments such as negative socket ID or NULL socket address structure. + + - [SOCK_ERR_INVALID](@ref SOCK_ERR_INVALID) + Indicate socket bind failure. +\section Example + This example demonstrates the call of the bind socket operation after a successful socket operation. +@code + struct sockaddr_in addr; + SOCKET udpServerSocket =-1; + int ret = -1; + + if(udpServerSocket == -1) + { + udpServerSocket = socket(AF_INET, SOCK_DGRAM, 0); + if(udpServerSocket >= 0) + { + addr.sin_family = AF_INET; + addr.sin_port = _htons(1234); + addr.sin_addr.s_addr = 0; + ret = bind(udpServerSocket,(struct sockaddr*)&addr,sizeof(addr)); + + if(ret != 0) + { + printf("Bind Failed. Error code = %d\n",ret); + close(udpServerSocket); + } + } + else + { + printf("UDP Server Socket Creation Failed\n"); + return; + } + } +@endcode +*/ +NMI_API sint8 bind(SOCKET sock, struct sockaddr *pstrAddr, uint8 u8AddrLen); + + +/** @} */ + +/** @defgroup ListenFn listen + * @ingroup SocketAPI + * After successful socket binding to an IP address and port on the system, start listening on a passive socket for incoming connections. + The socket must be bound on a local port or the listen operation fails. + Upon the call to the asynchronous listen function, response is received through the event [SOCKET_MSG_BIND](@ref SOCKET_MSG_BIND) + in the socket callback. + A successful listen means the TCP server operation is active. If a connection is accepted, then the application socket callback function is + notified with the new connected socket through the event @ref SOCKET_MSG_ACCEPT. Hence there is no need to call the @ref accept function + after calling @ref listen. + + After a connection is accepted, the user is then required to call the @ref recv to receive any packets transmitted by the remote host or to receive notification of socket connection + termination. + */ + /**@{*/ +/*! +@fn \ + NMI_API sint8 listen(SOCKET sock, uint8 backlog); + +@param [in] sock + Socket ID, must hold a non negative value. + A negative value will return a socket error @ref SOCK_ERR_INVALID_ARG. Indicating that an invalid argument is passed in. + +@param [in] backlog + Not used by the current implementation. + +@pre + The bind function must be called to assign the port number and IP address to the socket before the listen operation. + +@see + bind + accept + recv + recvfrom + send + sendto + +@return + The function returns ZERO for successful operations and a negative value otherwise. + The possible error values are: + - [SOCK_ERR_NO_ERROR](@ref SOCK_ERR_NO_ERROR) + Indicating that the operation was successful. + + - [SOCK_ERR_INVALID_ARG](@ref SOCK_ERR_INVALID_ARG) + Indicating passing invalid arguments such as negative socket ID. + + - [SOCK_ERR_INVALID](@ref SOCK_ERR_INVALID) + Indicate socket listen failure. +\section Example +This example demonstrates the call of the listen socket operation after a successful socket operation. +@code + static void TCP_Socketcallback(SOCKET sock, uint8 u8Msg, void * pvMsg) + { + int ret =-1; + + switch(u8Msg) + { + case SOCKET_MSG_BIND: + { + tstrSocketBindMsg *pstrBind = (tstrSocketBindMsg*)pvMsg; + if(pstrBind != NULL) + { + if(pstrBind->status == 0) + { + ret = listen(sock, 0); + + if(ret <0) + printf("Listen failure! Error = %d\n",ret); + } + else + { + M2M_ERR("bind Failure!\n"); + close(sock); + } + } + } + break; + + case SOCKET_MSG_LISTEN: + { + + tstrSocketListenMsg *pstrListen = (tstrSocketListenMsg*)pvMsg; + if(pstrListen != NULL) + { + if(pstrListen->status == 0) + { + ret = accept(sock,NULL,0); + } + else + { + M2M_ERR("listen Failure!\n"); + close(sock); + } + } + } + break; + + case SOCKET_MSG_ACCEPT: + { + tstrSocketAcceptMsg *pstrAccept = (tstrSocketAcceptMsg*)pvMsg; + + if(pstrAccept->sock >= 0) + { + TcpNotificationSocket = pstrAccept->sock; + recv(pstrAccept->sock,gau8RxBuffer,sizeof(gau8RxBuffer),TEST_RECV_TIMEOUT); + } + else + { + M2M_ERR("accept failure\n"); + } + } + break; + + default: + break; + } + } + +@endcode +*/ +NMI_API sint8 listen(SOCKET sock, uint8 backlog); +/** @} */ +/** @defgroup AcceptFn accept + * @ingroup SocketAPI + * The function has no current implementation. An empty deceleration is used to prevent errors when legacy application code is used. + * For recent application use, the accept function can be safer as it has no effect and could be safely removed from any application using it. + */ + /**@{*/ +/*! +@fn \ + NMI_API sint8 accept(SOCKET sock, struct sockaddr *addr, uint8 *addrlen); + +@param [in] sock + Socket ID, must hold a non negative value. + A negative value will return a socket error @ref SOCK_ERR_INVALID_ARG. Indicating that an invalid argument is passed in. +@param [in] addr + Not used in the current implementation. + +@param [in] addrlen + Not used in the current implementation. + +@return + The function returns ZERO for successful operations and a negative value otherwise. + The possible error values are: + - [SOCK_ERR_NO_ERROR](@ref SOCK_ERR_NO_ERROR) + Indicating that the operation was successful. + + - [SOCK_ERR_INVALID_ARG](@ref SOCK_ERR_INVALID_ARG) + Indicating passing invalid arguments such as negative socket ID. +*/ +NMI_API sint8 accept(SOCKET sock, struct sockaddr *addr, uint8 *addrlen); +/** @} */ +/** @defgroup ConnectFn connect + * @ingroup SocketAPI + * Establishes a TCP connection with a remote server. + The asynchronous connect function must be called after receiving a valid socket ID from the @ref socket function. + The application socket callback function is notified of a successful new socket connection through the event @ref SOCKET_MSG_CONNECT. + A successful connect means the TCP session is active. The application is then required to make a call to the @ref recv + to receive any packets transmitted by the remote server, unless the application is interrupted by a notification of socket connection + termination. + */ + /**@{*/ +/*! +@fn \ + NMI_API sint8 connect(SOCKET sock, struct sockaddr *pstrAddr, uint8 u8AddrLen); + +@param [in] sock + Socket ID, must hold a non negative value. + A negative value will return a socket error @ref SOCK_ERR_INVALID_ARG. Indicating that an invalid argument is passed in. + +@param [in] pstrAddr + Address of the remote server. +@param [in] pstrAddr + Pointer to socket address structure "sockaddr_in" + [sockaddr_in](@ref sockaddr_in) + +@param [in] u8AddrLen + Size of the given socket address structure in bytes. + Not currently used, implemented for BSD compatibility only. +@pre + The socket function must be called to allocate a TCP socket before passing the socket ID to the bind function. + If the socket is not bound, you do NOT have to call bind before the "connect" function. + +@see + socket + recv + send + close + +@return + The function returns ZERO for successful operations and a negative value otherwise. + The possible error values are: + - [SOCK_ERR_NO_ERROR](@ref SOCK_ERR_NO_ERROR) + Indicating that the operation was successful. + + - [SOCK_ERR_INVALID_ARG](@ref SOCK_ERR_INVALID_ARG) + Indicating passing invalid arguments such as negative socket ID or NULL socket address structure. + + - [SOCK_ERR_INVALID](@ref SOCK_ERR_INVALID) + Indicate socket connect failure. +\section Example + The example demonstrates a TCP application, showing how the asynchronous call to the connect function is made through the main function and how the + callback function handles the @ref SOCKET_MSG_CONNECT event. +\subsection sub1 Main Function +@code + struct sockaddr_in Serv_Addr; + SOCKET TcpClientSocket =-1; + int ret = -1 + + TcpClientSocket = socket(AF_INET,SOCK_STREAM,0); + Serv_Addr.sin_family = AF_INET; + Serv_Addr.sin_port = _htons(1234); + Serv_Addr.sin_addr.s_addr = inet_addr(SERVER); + printf("Connected to server via socket %u\n",TcpClientSocket); + + do + { + ret = connect(TcpClientSocket,(sockaddr_in*)&Serv_Addr,sizeof(Serv_Addr)); + if(ret != 0) + { + printf("Connection Error\n"); + } + else + { + printf("Connection successful.\n"); + break; + } + }while(1) +@endcode +\subsection sub2 Socket Callback +@code + if(u8Msg == SOCKET_MSG_CONNECT) + { + tstrSocketConnectMsg *pstrConnect = (tstrSocketConnectMsg*)pvMsg; + if(pstrConnect->s8Error == 0) + { + uint8 acBuffer[GROWL_MSG_SIZE]; + uint16 u16MsgSize; + + printf("Connect success!\n"); + + u16MsgSize = FormatMsg(u8ClientID, acBuffer); + send(sock, acBuffer, u16MsgSize, 0); + recv(pstrNotification->Socket, (void*)au8Msg,GROWL_DESCRIPTION_MAX_LENGTH, GROWL_RX_TIMEOUT); + u8Retry = GROWL_CONNECT_RETRY; + } + else + { + M2M_DBG("Connection Failed, Error: %d\n",pstrConnect->s8Error"); + close(pstrNotification->Socket); + } + } +@endcode +*/ +NMI_API sint8 connect(SOCKET sock, struct sockaddr *pstrAddr, uint8 u8AddrLen); +/** @} */ +/** @defgroup ReceiveFn recv + * @ingroup SocketAPI + * An asynchronous receive function, used to retrieve data from a TCP stream. + Before calling the recv function, a successful socket connection status must have been received through any of the two socket events + [SOCKET_MSG_CONNECT] or [SOCKET_MSG_ACCEPT], from the socket callback. Hence, indicating that the socket is already connected to a remote + host. + The application receives the required data in response to this asynchronous call through the reception of the event @ref SOCKET_MSG_RECV in the + socket callback. + + Receiving the SOCKET_MSG_RECV message in the callback with zero or negative buffer length indicates the following: + - SOCK_ERR_NO_ERROR : Socket connection closed + - SOCK_ERR_CONN_ABORTED : Socket connection aborted + - SOCK_ERR_TIMEOUT : Socket receive timed out + The application code is expected to close the socket through the call to the @ref close function upon the appearance of the above mentioned errors. + */ + /**@{*/ +/*! +@fn \ + NMI_API sint16 recv(SOCKET sock, void *pvRecvBuf, uint16 u16BufLen, uint32 u32Timeoutmsec); + +@param [in] sock + Socket ID, must hold a non negative value. + A negative value will return a socket error @ref SOCK_ERR_INVALID_ARG. Indicating that an invalid argument is passed in. + + +@param [in] pvRecvBuf + Pointer to a buffer that will hold the received data. The buffer is used + in the recv callback to deliver the received data to the caller. The buffer must + be resident in memory (heap or global buffer). + +@param [in] u16BufLen + The buffer size in bytes. + +@param [in] u32Timeoutmsec + Timeout for the recv function in milli-seconds. If the value is set to ZERO, the timeout + will be set to infinite (the recv function waits forever). If the timeout period is + elapsed with no data received, the socket will get a timeout error. +@pre + - The socket function must be called to allocate a TCP socket before passing the socket ID to the recv function. + - The socket in a connected state is expected to receive data through the socket interface. + +@see + socket + connect + bind + listen + recvfrom + close + + +@return + The function returns ZERO for successful operations and a negative value otherwise. + The possible error values are: + - [SOCK_ERR_NO_ERROR](@ref SOCK_ERR_NO_ERROR) + Indicating that the operation was successful. + + - [SOCK_ERR_INVALID_ARG](@ref SOCK_ERR_INVALID_ARG) + Indicating passing invalid arguments such as negative socket ID or NULL Recieve buffer. + + - [SOCK_ERR_BUFFER_FULL](@ref SOCK_ERR_BUFFER_FULL) + Indicate socket receive failure. +\section Example + The example demonstrates a code snippet for the calling of the recv function in the socket callback upon notification of the accept or connect events, and the parsing of the + received data when the SOCKET_MSG_RECV event is received. +@code + + switch(u8Msg) + { + + case SOCKET_MSG_ACCEPT: + { + tstrSocketAcceptMsg *pstrAccept = (tstrSocketAcceptMsg*)pvMsg; + + if(pstrAccept->sock >= 0) + { + recv(pstrAccept->sock,gau8RxBuffer,sizeof(gau8RxBuffer),TEST_RECV_TIMEOUT); + } + else + { + M2M_ERR("accept\n"); + } + } + break; + + + case SOCKET_MSG_RECV: + { + tstrSocketRecvMsg *pstrRx = (tstrSocketRecvMsg*)pvMsg; + + if(pstrRx->s16BufferSize > 0) + { + + recv(sock,gau8RxBuffer,sizeof(gau8RxBuffer),TEST_RECV_TIMEOUT); + } + else + { + printf("Socet recv Error: %d\n",pstrRx->s16BufferSize); + close(sock); + } + } + break; + + default: + break; + } +} +@endcode +*/ +NMI_API sint16 recv(SOCKET sock, void *pvRecvBuf, uint16 u16BufLen, uint32 u32Timeoutmsec); +/** @} */ +/** @defgroup ReceiveFromSocketFn recvfrom + * @ingroup SocketAPI + * Receives data from a UDP Socket. +* +* The asynchronous recvfrom function is used to retrieve data from a UDP socket. The socket must already be bound to +* a local port before a call to the recvfrom function is made (i.e message @ref SOCKET_MSG_BIND is received +* with successful status in the socket callback). +* +* Upon calling the recvfrom function with a successful return code, the application is expected to receive a notification +* in the socket callback whenever a message is received through the @ref SOCKET_MSG_RECVFROM event. +* +* Receiving the SOCKET_MSG_RECVFROM message in the callback with zero, indicates that the socket is closed. +* Whereby a negative buffer length indicates one of the socket error codes such as socket timeout error @SOCK_ERR_TIMEOUT: +* +* The recvfrom callback can also be used to show the IP address of the remote host that sent the frame by +* using the "strRemoteAddr" element in the @ref tstrSocketRecvMsg structure. (refer to the code example) + */ + /**@{*/ +/*! +@fn \ + NMI_API sint16 recvfrom(SOCKET sock, void *pvRecvBuf, uint16 u16BufLen, uint32 u32TimeoutSeconds); + +@param [in] sock + Socket ID, must hold a non negative value. + A negative value will return a socket error @ref SOCK_ERR_INVALID_ARG. Indicating that an invalid argument is passed in. + +@param [in] pvRecvBuf + Pointer to a buffer that will hold the received data. The buffer shall be used + in the recv callback to deliver the received data to the caller. The buffer must + be resident in memory (heap or global buffer). + +@param [in] u16BufLen + The buffer size in bytes. + +@param [in] u32TimeoutSeconds + Timeout for the recv function in milli-seconds. If the value is set to ZERO, the timeout + will be set to infinite (the recv function waits forever). + +@pre + - The socket function must be called to allocate a UDP socket before passing the socket ID to the recvfrom function. + - The socket corresponding to the socket ID must be successfully bound to a local port through the call to a @ref bind function. + +@see + socket + bind + close + +@return + The function returns ZERO for successful operations and a negative value otherwise. + The possible error values are: + - [SOCK_ERR_NO_ERROR](@ref SOCK_ERR_NO_ERROR) + Indicating that the operation was successful. + + - [SOCK_ERR_INVALID_ARG](@ref SOCK_ERR_INVALID_ARG) + Indicating passing invalid arguments such as negative socket ID or NULL Receive buffer. + + - [SOCK_ERR_BUFFER_FULL](@ref SOCK_ERR_BUFFER_FULL) + Indicate socket receive failure. +\section Example + The example demonstrates a code snippet for the calling of the recvfrom function in the socket callback upon notification of a successful bind event, and the parsing of the + received data when the SOCKET_MSG_RECVFROM event is received. +@code + switch(u8Msg) + { + + case SOCKET_MSG_BIND: + { + tstrSocketBindMsg *pstrBind = (tstrSocketBindMsg*)pvMsg; + + if(pstrBind != NULL) + { + if(pstrBind->status == 0) + { + recvfrom(sock, gau8SocketTestBuffer, TEST_BUFFER_SIZE, 0); + } + else + { + M2M_ERR("bind\n"); + } + } + } + break; + + + case SOCKET_MSG_RECVFROM: + { + tstrSocketRecvMsg *pstrRx = (tstrSocketRecvMsg*)pvMsg; + + if(pstrRx->s16BufferSize > 0) + { + //get the remote host address and port number + uint16 u16port = pstrRx->strRemoteAddr.sin_port; + uint32 strRemoteHostAddr = pstrRx->strRemoteAddr.sin_addr.s_addr; + + printf("Recieved frame with size = %d.\tHost address=%x, Port number = %d\n\n",pstrRx->s16BufferSize,strRemoteHostAddr, u16port); + + ret = recvfrom(sock,gau8SocketTestBuffer,sizeof(gau8SocketTestBuffer),TEST_RECV_TIMEOUT); + } + else + { + printf("Socet recv Error: %d\n",pstrRx->s16BufferSize); + ret = close(sock); + } + } + break; + + default: + break; + } +} +@endcode +*/ +NMI_API sint16 recvfrom(SOCKET sock, void *pvRecvBuf, uint16 u16BufLen, uint32 u32Timeoutmsec); +/** @} */ +/** @defgroup SendFn send + * @ingroup SocketAPI +* Asynchronous sending function, used to send data on a TCP/UDP socket. + +* Called by the application code when there is outgoing data available required to be sent on a specific socket handler. +* The only difference between this function and the similar @ref sendto function, is the type of socket the data is sent on and the parameters passed in. +* @ref send function is most commonly called for sockets in a connected state. +* After the data is sent, the socket callback function registered using registerSocketCallback(), is expected to receive an event of type +* @ref SOCKET_MSG_SEND holding information containing the number of data bytes sent. + */ + /**@{*/ +/*! +@fn \ + NMI_API sint16 send(SOCKET sock, void *pvSendBuffer, uint16 u16SendLength, uint16 u16Flags); + +@param [in] sock + Socket ID, must hold a non negative value. + A negative value will return a socket error @ref SOCK_ERR_INVALID_ARG. Indicating that an invalid argument is passed in. + +@param [in] pvSendBuffer + Pointer to a buffer holding data to be transmitted. + +@param [in] u16SendLength + The buffer size in bytes. + +@param [in] u16Flags + Not used in the current implementation. + +@pre + Sockets must be initialized using socketInit. \n + + For TCP Socket:\n + Must use a successfully connected Socket (so that the intended recipient address is known ahead of sending the data). + Hence this function is expected to be called after a successful socket connect operation(in client case or accept in the + the server case).\n + + For UDP Socket:\n + UDP sockets most commonly use @ref sendto function, where the destination address is defined. However, in-order to send outgoing data + using the @ref send function, at least one successful call must be made to the @ref sendto function a priori the consecutive calls to the @ref send function, + to ensure that the destination address is saved in the firmware. + +@see + socketInit + recv + sendto + socket + connect + accept + sendto + +@warning + u16SendLength must not exceed @ref SOCKET_BUFFER_MAX_LENGTH. \n + Use a valid socket identifier through the a prior call to the @ref socket function. + Must use a valid buffer pointer. + Successful completion of a call to send() does not guarantee delivery of the message, + A negative return value indicates only locally-detected errors + + +@return + The function shall return @ref SOCK_ERR_NO_ERROR for successful operation and a negative value (indicating the error) otherwise. +*/ +NMI_API sint16 send(SOCKET sock, void *pvSendBuffer, uint16 u16SendLength, uint16 u16Flags); +/** @} */ +/** @defgroup SendToSocketFn sendto + * @ingroup SocketAPI +* Asynchronous sending function, used to send data on a UDP socket. +* Called by the application code when there is data required to be sent on a UDP socket handler. +* The application code is expected to receive data from a successful bounded socket node. +* The only difference between this function and the similar @ref send function, is the type of socket the data is received on. This function works +* only with UDP sockets. +* After the data is sent, the socket callback function registered using registerSocketCallback(), is expected to receive an event of type +* @ref SOCKET_MSG_SENDTO. +*/ + /**@{*/ +/*! +@fn \ + NMI_API sint16 sendto(SOCKET sock, void *pvSendBuffer, uint16 u16SendLength, uint16 flags, struct sockaddr *pstrDestAddr, uint8 u8AddrLen); + +@param [in] sock + Socket ID, must hold a non negative value. + A negative value will return a socket error @ref SOCK_ERR_INVALID_ARG. Indicating that an invalid argument is passed in. + +@param [in] pvSendBuffer + Pointer to a buffer holding data to be transmitted. + A NULL value will return a socket error @ref SOCK_ERR_INVALID_ARG. Indicating that an invalid argument is passed in. + +@param [in] u16SendLength + The buffer size in bytes. It must not exceed @ref SOCKET_BUFFER_MAX_LENGTH. + +@param [in] flags + Not used in the current implementation + +@param [in] pstrDestAddr + The destination address. + +@param [in] u8AddrLen + Destination address length in bytes. + Not used in the current implementation, only included for BSD compatibility. +@pre + Sockets must be initialized using socketInit. + +@see + socketInit + recvfrom + sendto + socket + connect + accept + send + +@warning + u16SendLength must not exceed @ref SOCKET_BUFFER_MAX_LENGTH. \n + Use a valid socket (returned from socket ). + A valid buffer pointer must be used (not NULL). \n + Successful completion of a call to sendto() does not guarantee delivery of the message, + A negative return value indicates only locally-detected errors + +@return + The function returns @ref SOCK_ERR_NO_ERROR for successful operation and a negative value (indicating the error) otherwise. +*/ +NMI_API sint16 sendto(SOCKET sock, void *pvSendBuffer, uint16 u16SendLength, uint16 flags, struct sockaddr *pstrDestAddr, uint8 u8AddrLen); +/** @} */ +/** @defgroup CloseSocketFn close + * @ingroup SocketAPI + * Synchronous close function, releases all the socket assigned resources. + */ + /**@{*/ +/*! +@fn \ + NMI_API sint8 close(SOCKET sock); + +@param [in] sock + Socket ID, must hold a non negative value. + A negative value will return a socket error @ref SOCK_ERR_INVALID_ARG. Indicating that an invalid argument is passed in. + +@pre + Sockets must be initialized through the call of the socketInit function. + @ref close is called only for valid socket identifiers created through the @ref socket function. + +@warning + If @ref close is called while there are still pending messages (sent or received ) they will be discarded. + +@see + socketInit + socket + +@return + The function returned @ref SOCK_ERR_NO_ERROR for successful operation and a negative value (indicating the error) otherwise. +*/ +NMI_API sint8 close(SOCKET sock); + + +/** @} */ +/** @defgroup InetAddressFn nmi_inet_addr +* @ingroup SocketAPI +* Synchronous function which returns a BSD socket compliant Internet Protocol (IPv4) socket address. +* This IPv4 address in the input string parameter could either be specified as a host name, or as a numeric string representation like n.n.n.n known as the IPv4 dotted-decimal format +* (i.e. "192.168.10.1"). +* This function is used whenever an ip address needs to be set in the proper format +* (i.e. for the @ref tstrM2MIPConfig structure). +*/ + /**@{*/ +/*! +@fn \ + NMI_API uint32 nmi_inet_addr(char *pcIpAddr); + +@param [in] pcIpAddr + A null terminated string containing the IP address in IPv4 dotted-decimal address. + +@return + Unsigned 32-bit integer representing the IP address in Network byte order + (eg. "192.168.10.1" will be expressed as 0x010AA8C0). + +*/ +NMI_API uint32 nmi_inet_addr(char *pcIpAddr); + + +/** @} */ +/** @defgroup gethostbynameFn gethostbyname + * @ingroup SocketAPI +* Asynchronous DNS resolving function. This function use DNS to resolve a domain name into the corresponding IP address. +* A call to this function will cause a DNS request to be sent and the response will be delivered to the DNS callback function registered using registerSocketCallback() + */ + /**@{*/ +/*! +@fn \ + NMI_API sint8 gethostbyname(uint8 * pcHostName); + +@param [in] pcHostName + NULL terminated string containing the domain name for the remote host. + Its size must not exceed [HOSTNAME_MAX_SIZE](@ref HOSTNAME_MAX_SIZE). + +@see + registerSocketCallback + +@warning + Successful completion of a call to gethostbyname() does not guarantee success of the DNS request, + a negative return value indicates only locally-detected errors + +@return + - [SOCK_ERR_NO_ERROR](@ref SOCK_ERR_NO_ERROR) + - [SOCK_ERR_INVALID_ARG](@ref SOCK_ERR_INVALID_ARG) +*/ +NMI_API sint8 gethostbyname(uint8 * pcHostName); + + +/** @} */ +/** @defgroup sslEnableCertExpirationCheckFn sslEnableCertExpirationCheck + * @ingroup SocketAPI +* Configure the behavior of the SSL Library for Certificate Expiry Validation. + */ + /**@{*/ +/*! +@fn \ +NMI_API sint8 sslEnableCertExpirationCheck(tenuSslCertExpSettings enuValidationSetting); + +@param [in] enuValidationSetting + See @ref tenuSslCertExpSettings for details. + +@return + - [SOCK_ERR_NO_ERROR](@ref SOCK_ERR_NO_ERROR) for successful operation and negative error code otherwise. + +@sa tenuSslCertExpSettings +*/ +NMI_API sint8 sslEnableCertExpirationCheck(tenuSslCertExpSettings enuValidationSetting); + + +/** @} */ + +/** @defgroup SetSocketOptionFn setsockopt + * @ingroup SocketAPI +*The setsockopt() function shall set the option specified by the option_name +* argument, at the protocol level specified by the level argument, to the value +* pointed to by the option_value argument for the socket specified by the socket argument. +* +*

Possible protocol level values supported are @ref SOL_SOCKET and @ref SOL_SSL_SOCKET. +* Possible options when the protocol level is @ref SOL_SOCKET :

+* +* +* +* +* +* +* +* +* +* +* +* +* +*
@ref SO_SET_UDP_SEND_CALLBACKEnable/Disable callback messages for sendto(). +* Since UDP is unreliable by default the user maybe interested (or not) in +* receiving a message of @ref SOCKET_MSG_SENDTO for each call of sendto(). +* Enabled if option value equals @ref TRUE, disabled otherwise.
@ref IP_ADD_MEMBERSHIPValid for UDP sockets. This option is used to receive frames sent to +* a multicast group. option_value shall be a pointer to Unsigned 32-bit +* integer containing the multicast IPv4 address.
@ref IP_DROP_MEMBERSHIPValid for UDP sockets. This option is used to stop receiving frames +* sent to a multicast group. option_value shall be a pointer to Unsigned +* 32-bit integer containing the multicast IPv4 address.
+*

Possible options when the protcol leve  is @ref SOL_SSL_SOCKET

+* +* +* +* +* +* +* +* +* +* +* +* +* +*
+* @ref SO_SSL_BYPASS_X509_VERIFAllow an opened SSL socket to bypass the X509 +* certificate verification process. It is highly recommended NOT to use +* this socket option in production software applications. The option is +* supported for debugging and testing purposes. The option value should be +* casted to int type and it is handled as a boolean flag.
@ref SO_SSL_SNISet the Server Name Indicator (SNI) for an SSL socket. The SNI is a +* null terminated string containing the server name associated with the +* connection. It must not exceed the size of @ref HOSTNAME_MAX_SIZE.
@ref SO_SSL_ENABLE_SESSION_CACHINGThis option allow the TLS to cache the session information for fast +* TLS session establishment in future connections using the TLS Protocol +* session resume features.
+ */ + /**@{*/ +/*! +@fn \ + NMI_API sint8 setsockopt(SOCKET socket, uint8 u8Level, uint8 option_name, + const void *option_value, uint16 u16OptionLen); + +@param [in] sock + Socket handler. + +@param [in] level + protocol level. See description above. + +@param [in] option_name + option to be set. See description above. + +@param [in] option_value + pointer to user provided value. + +@param [in] option_len + length of the option value in bytes. +@return + The function shall return \ref SOCK_ERR_NO_ERROR for successful operation + and a negative value (indicating the error) otherwise. +@sa SOL_SOCKET, SOL_SSL_SOCKET, IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP +*/ +NMI_API sint8 setsockopt(SOCKET socket, uint8 u8Level, uint8 option_name, + const void *option_value, uint16 u16OptionLen); + + +/** @} */ +/** @defgroup GetSocketOptionsFn getsockopt + * @ingroup SocketAPI + * Get socket options retrieves +* This Function isn't implemented yet but this is the form that will be released later. + */ + /**@{*/ +/*! +@fn \ + sint8 getsockopt(SOCKET sock, uint8 u8Level, uint8 u8OptName, const void *pvOptValue, uint8 * pu8OptLen); + +@brief + +@param [in] sock + Socket Identifie. +@param [in] u8Level + The protocol level of the option. +@param [in] u8OptName + The u8OptName argument specifies a single option to get. +@param [out] pvOptValue + The pvOptValue argument contains pointer to a buffer containing the option value. +@param [out] pu8OptLen + Option value buffer length. +@return + The function shall return ZERO for successful operation and a negative value otherwise. +*/ +NMI_API sint8 getsockopt(SOCKET sock, uint8 u8Level, uint8 u8OptName, const void *pvOptValue, uint8* pu8OptLen); +/** @} */ + +/**@}*/ +/** @defgroup PingFn m2m_ping_req + * @ingroup SocketAPI + * The function sends ping request to the given IP Address. + */ + /**@{*/ +/*! +@fn \ + NMI_API sint8 m2m_ping_req(uint32 u32DstIP, uint8 u8TTL, tpfPingCb fpPingCb); + +@param [in] u32DstIP + Target Destination IP Address for the ping request. It must be represented in Network byte order. + The function nmi_inet_addr could be used to translate the dotted decimal notation IP + to its Network bytes order integer represntative. + +@param [in] u8TTL + IP TTL value for the ping request. If set to ZERO, the dfault value SHALL be used. + +@param [in] fpPingCb + Callback will be called to deliver the ping statistics. + +@see nmi_inet_addr +@return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. +*/ +NMI_API sint8 m2m_ping_req(uint32 u32DstIP, uint8 u8TTL, tpfPingCb fpPingCb); +/**@}*/ + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __SOCKET_H__ */ diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/socket/source/socket.c b/ext/hal/atmel/asf/common/components/wifi/winc1500/socket/source/socket.c new file mode 100644 index 0000000000000..66c7a2bed42e9 --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/socket/source/socket.c @@ -0,0 +1,1309 @@ +/** + * + * \file + * + * \brief BSD compatible socket interface. + * + * Copyright (c) 2016-2017 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +INCLUDES +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ + +#include "bsp/include/nm_bsp.h" +#include "socket/include/socket.h" +#include "driver/source/m2m_hif.h" +#include "socket/source/socket_internal.h" +#include "driver/include/m2m_types.h" + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +MACROS +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ + + +#define TLS_RECORD_HEADER_LENGTH (5) +#define ETHERNET_HEADER_OFFSET (34) +#define ETHERNET_HEADER_LENGTH (14) +#define TCP_IP_HEADER_LENGTH (40) +#define UDP_IP_HEADER_LENGTH (28) + +#define IP_PACKET_OFFSET (ETHERNET_HEADER_LENGTH + ETHERNET_HEADER_OFFSET - M2M_HIF_HDR_OFFSET) + +#define TCP_TX_PACKET_OFFSET (IP_PACKET_OFFSET + TCP_IP_HEADER_LENGTH) +#define UDP_TX_PACKET_OFFSET (IP_PACKET_OFFSET + UDP_IP_HEADER_LENGTH) +#define SSL_TX_PACKET_OFFSET (TCP_TX_PACKET_OFFSET + TLS_RECORD_HEADER_LENGTH) + +#define SOCKET_REQUEST(reqID, reqArgs, reqSize, reqPayload, reqPayloadSize, reqPayloadOffset) \ + hif_send(M2M_REQ_GROUP_IP, reqID, reqArgs, reqSize, reqPayload, reqPayloadSize, reqPayloadOffset) + + +#define SSL_FLAGS_ACTIVE NBIT0 +#define SSL_FLAGS_BYPASS_X509 NBIT1 +#define SSL_FLAGS_2_RESERVD NBIT2 +#define SSL_FLAGS_3_RESERVD NBIT3 +#define SSL_FLAGS_CACHE_SESSION NBIT4 +#define SSL_FLAGS_NO_TX_COPY NBIT5 +#define SSL_FLAGS_CHECK_SNI NBIT6 + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +PRIVATE DATA TYPES +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ + + +/*! +* @brief +*/ +typedef struct{ + SOCKET sock; + uint8 u8Dummy; + uint16 u16SessionID; +}tstrCloseCmd; + + +/*! +* @brief +*/ +typedef struct{ + uint8 *pu8UserBuffer; + uint16 u16UserBufferSize; + uint16 u16SessionID; + uint16 u16DataOffset; + uint8 bIsUsed; + uint8 u8SSLFlags; + uint8 bIsRecvPending; +}tstrSocket; + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +GLOBALS +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ + +volatile sint8 gsockerrno; +volatile tstrSocket gastrSockets[MAX_SOCKET]; +volatile uint8 gu8OpCode; +volatile uint16 gu16BufferSize; +volatile uint16 gu16SessionID = 0; + +volatile tpfAppSocketCb gpfAppSocketCb; +volatile tpfAppResolveCb gpfAppResolveCb; +volatile uint8 gbSocketInit = 0; +volatile tpfPingCb gfpPingCb; + +/********************************************************************* +Function + Socket_ReadSocketData + +Description + Callback function used by the NMC1500 driver to deliver messages + for socket layer. + +Return + None. + +Author + Ahmed Ezzat + +Version + 1.0 + +Date + 17 July 2012 +*********************************************************************/ +NMI_API void Socket_ReadSocketData(SOCKET sock, tstrSocketRecvMsg *pstrRecv,uint8 u8SocketMsg, + uint32 u32StartAddress,uint16 u16ReadCount) +{ + if((u16ReadCount > 0) && (gastrSockets[sock].pu8UserBuffer != NULL) && (gastrSockets[sock].u16UserBufferSize > 0) && (gastrSockets[sock].bIsUsed == 1)) + { + uint32 u32Address = u32StartAddress; + uint16 u16Read; + sint16 s16Diff; + uint8 u8SetRxDone; + + pstrRecv->u16RemainingSize = u16ReadCount; + do + { + u8SetRxDone = 1; + u16Read = u16ReadCount; + s16Diff = u16Read - gastrSockets[sock].u16UserBufferSize; + if(s16Diff > 0) + { + u8SetRxDone = 0; + u16Read = gastrSockets[sock].u16UserBufferSize; + } + + if(hif_receive(u32Address, gastrSockets[sock].pu8UserBuffer, u16Read, u8SetRxDone) == M2M_SUCCESS) + { + pstrRecv->pu8Buffer = gastrSockets[sock].pu8UserBuffer; + pstrRecv->s16BufferSize = u16Read; + pstrRecv->u16RemainingSize -= u16Read; + + if (gpfAppSocketCb) + gpfAppSocketCb(sock,u8SocketMsg, pstrRecv); + + u16ReadCount -= u16Read; + u32Address += u16Read; + + if((!gastrSockets[sock].bIsUsed) && (u16ReadCount)) + { + M2M_DBG("Application Closed Socket While Rx Is not Complete\n"); + if(hif_receive(0, NULL, 0, 1) == M2M_SUCCESS) + M2M_DBG("hif_receive Success\n"); + else + M2M_DBG("hif_receive Fail\n"); + break; + } + } + else + { + M2M_INFO("(ERRR)Current <%d>\n", u16ReadCount); + break; + } + }while(u16ReadCount != 0); + } +} +/********************************************************************* +Function + m2m_ip_cb + +Description + Callback function used by the NMC1000 driver to deliver messages + for socket layer. + +Return + None. + +Author + Ahmed Ezzat + +Version + 1.0 + +Date + 17 July 2012 +*********************************************************************/ +static void m2m_ip_cb(uint8 u8OpCode, uint16 u16BufferSize,uint32 u32Address) +{ + if((u8OpCode == SOCKET_CMD_BIND) || (u8OpCode == SOCKET_CMD_SSL_BIND)) + { + tstrBindReply strBindReply; + tstrSocketBindMsg strBind; + + if(hif_receive(u32Address, (uint8*)&strBindReply, sizeof(tstrBindReply), 0) == M2M_SUCCESS) + { + strBind.status = strBindReply.s8Status; + if(gpfAppSocketCb) + gpfAppSocketCb(strBindReply.sock,SOCKET_MSG_BIND,&strBind); + } + } + else if(u8OpCode == SOCKET_CMD_LISTEN) + { + tstrListenReply strListenReply; + tstrSocketListenMsg strListen; + if(hif_receive(u32Address, (uint8*)&strListenReply, sizeof(tstrListenReply), 0) == M2M_SUCCESS) + { + strListen.status = strListenReply.s8Status; + if(gpfAppSocketCb) + gpfAppSocketCb(strListenReply.sock,SOCKET_MSG_LISTEN, &strListen); + } + } + else if(u8OpCode == SOCKET_CMD_ACCEPT) + { + tstrAcceptReply strAcceptReply; + tstrSocketAcceptMsg strAccept; + if(hif_receive(u32Address, (uint8*)&strAcceptReply, sizeof(tstrAcceptReply), 0) == M2M_SUCCESS) + { + if(strAcceptReply.sConnectedSock >= 0) + { + gastrSockets[strAcceptReply.sConnectedSock].u8SSLFlags = gastrSockets[strAcceptReply.sListenSock].u8SSLFlags; + gastrSockets[strAcceptReply.sConnectedSock].bIsUsed = 1; + gastrSockets[strAcceptReply.sConnectedSock].u16DataOffset = strAcceptReply.u16AppDataOffset - M2M_HIF_HDR_OFFSET; + + /* The session ID is used to distinguish different socket connections + by comparing the assigned session ID to the one reported by the firmware*/ + ++gu16SessionID; + if(gu16SessionID == 0) + ++gu16SessionID; + + gastrSockets[strAcceptReply.sConnectedSock].u16SessionID = gu16SessionID; + M2M_DBG("Socket %d session ID = %d\r\n",strAcceptReply.sConnectedSock , gu16SessionID ); + } + strAccept.sock = strAcceptReply.sConnectedSock; + strAccept.strAddr.sin_family = AF_INET; + strAccept.strAddr.sin_port = strAcceptReply.strAddr.u16Port; + strAccept.strAddr.sin_addr.s_addr = strAcceptReply.strAddr.u32IPAddr; + if(gpfAppSocketCb) + gpfAppSocketCb(strAcceptReply.sListenSock, SOCKET_MSG_ACCEPT, &strAccept); + } + } + else if((u8OpCode == SOCKET_CMD_CONNECT) || (u8OpCode == SOCKET_CMD_SSL_CONNECT)) + { + tstrConnectReply strConnectReply; + tstrSocketConnectMsg strConnMsg; + if(hif_receive(u32Address, (uint8*)&strConnectReply, sizeof(tstrConnectReply), 0) == M2M_SUCCESS) + { + strConnMsg.sock = strConnectReply.sock; + strConnMsg.s8Error = strConnectReply.s8Error; + if(strConnectReply.s8Error == SOCK_ERR_NO_ERROR) + { + gastrSockets[strConnectReply.sock].u16DataOffset = strConnectReply.u16AppDataOffset - M2M_HIF_HDR_OFFSET; + } + if(gpfAppSocketCb) + gpfAppSocketCb(strConnectReply.sock,SOCKET_MSG_CONNECT, &strConnMsg); + } + } + else if(u8OpCode == SOCKET_CMD_DNS_RESOLVE) + { + tstrDnsReply strDnsReply; + if(hif_receive(u32Address, (uint8*)&strDnsReply, sizeof(tstrDnsReply), 0) == M2M_SUCCESS) + { + if(gpfAppResolveCb) + gpfAppResolveCb((uint8*)strDnsReply.acHostName, strDnsReply.u32HostIP); + } + } + else if((u8OpCode == SOCKET_CMD_RECV) || (u8OpCode == SOCKET_CMD_RECVFROM) || (u8OpCode == SOCKET_CMD_SSL_RECV)) + { + SOCKET sock; + sint16 s16RecvStatus; + tstrRecvReply strRecvReply; + uint16 u16ReadSize; + tstrSocketRecvMsg strRecvMsg; + uint8 u8CallbackMsgID = SOCKET_MSG_RECV; + uint16 u16DataOffset; + + if(u8OpCode == SOCKET_CMD_RECVFROM) + u8CallbackMsgID = SOCKET_MSG_RECVFROM; + + /* Read RECV REPLY data structure. + */ + u16ReadSize = sizeof(tstrRecvReply); + if(hif_receive(u32Address, (uint8*)&strRecvReply, u16ReadSize, 0) == M2M_SUCCESS) + { + uint16 u16SessionID = 0; + + sock = strRecvReply.sock; + u16SessionID = strRecvReply.u16SessionID; + M2M_DBG("recv callback session ID = %d\r\n",u16SessionID); + + /* Reset the Socket RX Pending Flag. + */ + gastrSockets[sock].bIsRecvPending = 0; + + s16RecvStatus = NM_BSP_B_L_16(strRecvReply.s16RecvStatus); + u16DataOffset = NM_BSP_B_L_16(strRecvReply.u16DataOffset); + strRecvMsg.strRemoteAddr.sin_port = strRecvReply.strRemoteAddr.u16Port; + strRecvMsg.strRemoteAddr.sin_addr.s_addr = strRecvReply.strRemoteAddr.u32IPAddr; + + if(u16SessionID == gastrSockets[sock].u16SessionID) + { + if((s16RecvStatus > 0) && (s16RecvStatus < u16BufferSize)) + { + /* Skip incoming bytes until reaching the Start of Application Data. + */ + u32Address += u16DataOffset; + + /* Read the Application data and deliver it to the application callback in + the given application buffer. If the buffer is smaller than the received data, + the data is passed to the application in chunks according to its buffer size. + */ + u16ReadSize = (uint16)s16RecvStatus; + Socket_ReadSocketData(sock, &strRecvMsg, u8CallbackMsgID, u32Address, u16ReadSize); + } + else + { + strRecvMsg.s16BufferSize = s16RecvStatus; + strRecvMsg.pu8Buffer = NULL; + if(gpfAppSocketCb) + gpfAppSocketCb(sock,u8CallbackMsgID, &strRecvMsg); + } + } + else + { + M2M_DBG("Discard recv callback %d %d \r\n",u16SessionID , gastrSockets[sock].u16SessionID); + if(u16ReadSize < u16BufferSize) + { + if(hif_receive(0, NULL, 0, 1) == M2M_SUCCESS) + M2M_DBG("hif_receive Success\n"); + else + M2M_DBG("hif_receive Fail\n"); + } + } + } + } + else if((u8OpCode == SOCKET_CMD_SEND) || (u8OpCode == SOCKET_CMD_SENDTO) || (u8OpCode == SOCKET_CMD_SSL_SEND)) + { + SOCKET sock; + sint16 s16Rcvd; + tstrSendReply strReply; + uint8 u8CallbackMsgID = SOCKET_MSG_SEND; + + if(u8OpCode == SOCKET_CMD_SENDTO) + u8CallbackMsgID = SOCKET_MSG_SENDTO; + + if(hif_receive(u32Address, (uint8*)&strReply, sizeof(tstrSendReply), 0) == M2M_SUCCESS) + { + uint16 u16SessionID = 0; + + sock = strReply.sock; + u16SessionID = strReply.u16SessionID; + M2M_DBG("send callback session ID = %d\r\n",u16SessionID); + + s16Rcvd = NM_BSP_B_L_16(strReply.s16SentBytes); + + if(u16SessionID == gastrSockets[sock].u16SessionID) + { + if(gpfAppSocketCb) + gpfAppSocketCb(sock,u8CallbackMsgID, &s16Rcvd); + } + else + { + M2M_DBG("Discard send callback %d %d \r\n",u16SessionID , gastrSockets[sock].u16SessionID); + } + } + } + else if(u8OpCode == SOCKET_CMD_PING) + { + tstrPingReply strPingReply; + if(hif_receive(u32Address, (uint8*)&strPingReply, sizeof(tstrPingReply), 1) == M2M_SUCCESS) + { + gfpPingCb = (void (*)(uint32 , uint32 , uint8))strPingReply.u32CmdPrivate; + if(gfpPingCb != NULL) + { + gfpPingCb(strPingReply.u32IPAddr, strPingReply.u32RTT, strPingReply.u8ErrorCode); + } + } + } +} +/********************************************************************* +Function + socketInit + +Description + +Return + None. + +Author + Ahmed Ezzat + +Version + 1.0 + +Date + 4 June 2012 +*********************************************************************/ +void socketInit(void) +{ + if(gbSocketInit == 0) + { + m2m_memset((uint8*)gastrSockets, 0, MAX_SOCKET * sizeof(tstrSocket)); + hif_register_cb(M2M_REQ_GROUP_IP,m2m_ip_cb); + gbSocketInit = 1; + gu16SessionID = 0; + } +} +/********************************************************************* +Function + socketDeinit + +Description + +Return + None. + +Author + Samer Sarhan + +Version + 1.0 + +Date + 27 Feb 2015 +*********************************************************************/ +void socketDeinit(void) +{ + m2m_memset((uint8*)gastrSockets, 0, MAX_SOCKET * sizeof(tstrSocket)); + hif_register_cb(M2M_REQ_GROUP_IP, NULL); + gpfAppSocketCb = NULL; + gpfAppResolveCb = NULL; + gbSocketInit = 0; +} +/********************************************************************* +Function + registerSocketCallback + +Description + +Return + None. + +Author + Ahmed Ezzat + +Versio + 1.0 + +Date + 4 June 2012 +*********************************************************************/ +void registerSocketCallback(tpfAppSocketCb pfAppSocketCb, tpfAppResolveCb pfAppResolveCb) +{ + gpfAppSocketCb = pfAppSocketCb; + gpfAppResolveCb = pfAppResolveCb; +} + +/********************************************************************* +Function + socket + +Description + Creates a socket. + +Return + - Negative value for error. + - ZERO or positive value as a socket ID if successful. + +Author + Ahmed Ezzat + +Version + 1.0 + +Date + 4 June 2012 +*********************************************************************/ +SOCKET socket(uint16 u16Domain, uint8 u8Type, uint8 u8Flags) +{ + SOCKET sock = -1; + uint8 u8SockID; + uint8 u8Count; + volatile tstrSocket *pstrSock; + static volatile uint8 u8NextTcpSock = 0; + static volatile uint8 u8NextUdpSock = 0; + + /* The only supported family is the AF_INET for UDP and TCP transport layer protocols. */ + if(u16Domain == AF_INET) + { + if(u8Type == SOCK_STREAM) + { + for(u8Count = 0; u8Count < TCP_SOCK_MAX; u8Count ++) + { + u8SockID = u8NextTcpSock; + pstrSock = &gastrSockets[u8NextTcpSock]; + u8NextTcpSock = (u8NextTcpSock + 1) % TCP_SOCK_MAX; + if(!pstrSock->bIsUsed) + { + sock = (SOCKET)u8SockID; + break; + } + } + } + else if(u8Type == SOCK_DGRAM) + { + volatile tstrSocket *pastrUDPSockets = &gastrSockets[TCP_SOCK_MAX]; + for(u8Count = 0; u8Count < UDP_SOCK_MAX; u8Count ++) + { + u8SockID = u8NextUdpSock; + pstrSock = &pastrUDPSockets[u8NextUdpSock]; + u8NextUdpSock = (u8NextUdpSock + 1) % UDP_SOCK_MAX; + if(!pstrSock->bIsUsed) + { + sock = (SOCKET)(u8SockID + TCP_SOCK_MAX); + break; + } + } + } + + if(sock >= 0) + { + m2m_memset((uint8*)pstrSock, 0, sizeof(tstrSocket)); + pstrSock->bIsUsed = 1; + + /* The session ID is used to distinguish different socket connections + by comparing the assigned session ID to the one reported by the firmware*/ + ++gu16SessionID; + if(gu16SessionID == 0) + ++gu16SessionID; + + pstrSock->u16SessionID = gu16SessionID; + M2M_INFO("Socket %d session ID = %d\r\n",sock, gu16SessionID ); + + if(u8Flags & SOCKET_FLAGS_SSL) + { + tstrSSLSocketCreateCmd strSSLCreate; + strSSLCreate.sslSock = sock; + pstrSock->u8SSLFlags = SSL_FLAGS_ACTIVE | SSL_FLAGS_NO_TX_COPY; + SOCKET_REQUEST(SOCKET_CMD_SSL_CREATE, (uint8*)&strSSLCreate, sizeof(tstrSSLSocketCreateCmd), 0, 0, 0); + } + } + } + return sock; +} +/********************************************************************* +Function + bind + +Description + Request to bind a socket on a local address. + +Return + + +Author + Ahmed Ezzat + +Version + 1.0 + +Date + 5 June 2012 +*********************************************************************/ +sint8 bind(SOCKET sock, struct sockaddr *pstrAddr, uint8 u8AddrLen) +{ + sint8 s8Ret = SOCK_ERR_INVALID_ARG; + if((pstrAddr != NULL) && (sock >= 0) && (gastrSockets[sock].bIsUsed == 1) && (u8AddrLen != 0)) + { + tstrBindCmd strBind; + uint8 u8CMD = SOCKET_CMD_BIND; + if(gastrSockets[sock].u8SSLFlags & SSL_FLAGS_ACTIVE) + { + u8CMD = SOCKET_CMD_SSL_BIND; + } + + /* Build the bind request. */ + strBind.sock = sock; + m2m_memcpy((uint8 *)&strBind.strAddr, (uint8 *)pstrAddr, sizeof(tstrSockAddr)); + strBind.u16SessionID = gastrSockets[sock].u16SessionID; + + /* Send the request. */ + s8Ret = SOCKET_REQUEST(u8CMD, (uint8*)&strBind,sizeof(tstrBindCmd) , NULL , 0, 0); + if(s8Ret != SOCK_ERR_NO_ERROR) + { + s8Ret = SOCK_ERR_INVALID; + } + } + return s8Ret; +} +/********************************************************************* +Function + listen + +Description + + +Return + + +Author + Ahmed Ezzat + +Version + 1.0 + +Date + 5 June 2012 +*********************************************************************/ +sint8 listen(SOCKET sock, uint8 backlog) +{ + sint8 s8Ret = SOCK_ERR_INVALID_ARG; + + if(sock >= 0 && (gastrSockets[sock].bIsUsed == 1)) + { + tstrListenCmd strListen; + + strListen.sock = sock; + strListen.u8BackLog = backlog; + strListen.u16SessionID = gastrSockets[sock].u16SessionID; + + s8Ret = SOCKET_REQUEST(SOCKET_CMD_LISTEN, (uint8*)&strListen, sizeof(tstrListenCmd), NULL, 0, 0); + if(s8Ret != SOCK_ERR_NO_ERROR) + { + s8Ret = SOCK_ERR_INVALID; + } + } + return s8Ret; +} +/********************************************************************* +Function + accept + +Description + +Return + + +Author + Ahmed Ezzat + +Version + 1.0 + +Date + 5 June 2012 +*********************************************************************/ +sint8 accept(SOCKET sock, struct sockaddr *addr, uint8 *addrlen) +{ + sint8 s8Ret = SOCK_ERR_INVALID_ARG; + + if(sock >= 0 && (gastrSockets[sock].bIsUsed == 1) ) + { + s8Ret = SOCK_ERR_NO_ERROR; + } + return s8Ret; +} +/********************************************************************* +Function + connect + +Description + Connect to a remote TCP Server. + +Return + + +Author + Ahmed Ezzat + +Version + 1.0 + +Date + 5 June 2012 +*********************************************************************/ +sint8 connect(SOCKET sock, struct sockaddr *pstrAddr, uint8 u8AddrLen) +{ + sint8 s8Ret = SOCK_ERR_INVALID_ARG; + if((sock >= 0) && (pstrAddr != NULL) && (gastrSockets[sock].bIsUsed == 1) && (u8AddrLen != 0)) + { + tstrConnectCmd strConnect; + uint8 u8Cmd = SOCKET_CMD_CONNECT; + if((gastrSockets[sock].u8SSLFlags) & SSL_FLAGS_ACTIVE) + { + u8Cmd = SOCKET_CMD_SSL_CONNECT; + strConnect.u8SslFlags = gastrSockets[sock].u8SSLFlags; + } + strConnect.sock = sock; + m2m_memcpy((uint8 *)&strConnect.strAddr, (uint8 *)pstrAddr, sizeof(tstrSockAddr)); + + strConnect.u16SessionID = gastrSockets[sock].u16SessionID; + s8Ret = SOCKET_REQUEST(u8Cmd, (uint8*)&strConnect,sizeof(tstrConnectCmd), NULL, 0, 0); + if(s8Ret != SOCK_ERR_NO_ERROR) + { + s8Ret = SOCK_ERR_INVALID; + } + } + return s8Ret; +} +/********************************************************************* +Function + send + +Description + +Return + +Author + Ahmed Ezzat + +Version + 1.0 + +Date + 5 June 2012 +*********************************************************************/ +sint16 send(SOCKET sock, void *pvSendBuffer, uint16 u16SendLength, uint16 flags) +{ + sint16 s16Ret = SOCK_ERR_INVALID_ARG; + + if((sock >= 0) && (pvSendBuffer != NULL) && (u16SendLength <= SOCKET_BUFFER_MAX_LENGTH) && (gastrSockets[sock].bIsUsed == 1)) + { + uint16 u16DataOffset; + tstrSendCmd strSend; + uint8 u8Cmd; + + u8Cmd = SOCKET_CMD_SEND; + u16DataOffset = TCP_TX_PACKET_OFFSET; + + strSend.sock = sock; + strSend.u16DataSize = NM_BSP_B_L_16(u16SendLength); + strSend.u16SessionID = gastrSockets[sock].u16SessionID; + + if(sock >= TCP_SOCK_MAX) + { + u16DataOffset = UDP_TX_PACKET_OFFSET; + } + if(gastrSockets[sock].u8SSLFlags & SSL_FLAGS_ACTIVE) + { + u8Cmd = SOCKET_CMD_SSL_SEND; + u16DataOffset = gastrSockets[sock].u16DataOffset; + } + + s16Ret = SOCKET_REQUEST(u8Cmd|M2M_REQ_DATA_PKT, (uint8*)&strSend, sizeof(tstrSendCmd), pvSendBuffer, u16SendLength, u16DataOffset); + if(s16Ret != SOCK_ERR_NO_ERROR) + { + s16Ret = SOCK_ERR_BUFFER_FULL; + } + } + return s16Ret; +} +/********************************************************************* +Function + sendto + +Description + +Return + +Author + Ahmed Ezzat + +Version + 1.0 + +Date + 4 June 2012 +*********************************************************************/ +sint16 sendto(SOCKET sock, void *pvSendBuffer, uint16 u16SendLength, uint16 flags, struct sockaddr *pstrDestAddr, uint8 u8AddrLen) +{ + sint16 s16Ret = SOCK_ERR_INVALID_ARG; + + if((sock >= 0) && (pvSendBuffer != NULL) && (u16SendLength <= SOCKET_BUFFER_MAX_LENGTH) && (gastrSockets[sock].bIsUsed == 1)) + { + if(gastrSockets[sock].bIsUsed) + { + tstrSendCmd strSendTo; + + m2m_memset((uint8*)&strSendTo, 0, sizeof(tstrSendCmd)); + + strSendTo.sock = sock; + strSendTo.u16DataSize = NM_BSP_B_L_16(u16SendLength); + strSendTo.u16SessionID = gastrSockets[sock].u16SessionID; + + if(pstrDestAddr != NULL) + { + struct sockaddr_in *pstrAddr; + pstrAddr = (void*)pstrDestAddr; + + strSendTo.strAddr.u16Family = pstrAddr->sin_family; + strSendTo.strAddr.u16Port = pstrAddr->sin_port; + strSendTo.strAddr.u32IPAddr = pstrAddr->sin_addr.s_addr; + } + s16Ret = SOCKET_REQUEST(SOCKET_CMD_SENDTO|M2M_REQ_DATA_PKT, (uint8*)&strSendTo, sizeof(tstrSendCmd), + pvSendBuffer, u16SendLength, UDP_TX_PACKET_OFFSET); + + if(s16Ret != SOCK_ERR_NO_ERROR) + { + s16Ret = SOCK_ERR_BUFFER_FULL; + } + } + } + return s16Ret; +} +/********************************************************************* +Function + recv + +Description + +Return + + +Author + Ahmed Ezzat + +Version + 1.0 + 2.0 9 April 2013 --> Add timeout for recv operation. + +Date + 5 June 2012 +*********************************************************************/ +sint16 recv(SOCKET sock, void *pvRecvBuf, uint16 u16BufLen, uint32 u32Timeoutmsec) +{ + sint16 s16Ret = SOCK_ERR_INVALID_ARG; + + if((sock >= 0) && (pvRecvBuf != NULL) && (u16BufLen != 0) && (gastrSockets[sock].bIsUsed == 1)) + { + s16Ret = SOCK_ERR_NO_ERROR; + gastrSockets[sock].pu8UserBuffer = (uint8*)pvRecvBuf; + gastrSockets[sock].u16UserBufferSize = u16BufLen; + + if(!gastrSockets[sock].bIsRecvPending) + { + tstrRecvCmd strRecv; + uint8 u8Cmd = SOCKET_CMD_RECV; + + gastrSockets[sock].bIsRecvPending = 1; + if(gastrSockets[sock].u8SSLFlags & SSL_FLAGS_ACTIVE) + { + u8Cmd = SOCKET_CMD_SSL_RECV; + } + + /* Check the timeout value. */ + if(u32Timeoutmsec == 0) + strRecv.u32Timeoutmsec = 0xFFFFFFFF; + else + strRecv.u32Timeoutmsec = NM_BSP_B_L_32(u32Timeoutmsec); + strRecv.sock = sock; + strRecv.u16SessionID = gastrSockets[sock].u16SessionID; + + s16Ret = SOCKET_REQUEST(u8Cmd, (uint8*)&strRecv, sizeof(tstrRecvCmd), NULL , 0, 0); + if(s16Ret != SOCK_ERR_NO_ERROR) + { + s16Ret = SOCK_ERR_BUFFER_FULL; + } + } + } + return s16Ret; +} +/********************************************************************* +Function + close + +Description + +Return + None. + +Author + Ahmed Ezzat + +Version + 1.0 + +Date + 4 June 2012 +*********************************************************************/ +sint8 close(SOCKET sock) +{ + sint8 s8Ret = SOCK_ERR_INVALID_ARG; + M2M_INFO("Sock to delete <%d>\n", sock); + if(sock >= 0 && (gastrSockets[sock].bIsUsed == 1)) + { + uint8 u8Cmd = SOCKET_CMD_CLOSE; + tstrCloseCmd strclose; + strclose.sock = sock; + strclose.u16SessionID = gastrSockets[sock].u16SessionID; + + gastrSockets[sock].bIsUsed = 0; + gastrSockets[sock].u16SessionID =0; + + if(gastrSockets[sock].u8SSLFlags & SSL_FLAGS_ACTIVE) + { + u8Cmd = SOCKET_CMD_SSL_CLOSE; + } + s8Ret = SOCKET_REQUEST(u8Cmd, (uint8*)&strclose, sizeof(tstrCloseCmd), NULL,0, 0); + if(s8Ret != SOCK_ERR_NO_ERROR) + { + s8Ret = SOCK_ERR_INVALID; + } + m2m_memset((uint8*)&gastrSockets[sock], 0, sizeof(tstrSocket)); + } + return s8Ret; +} +/********************************************************************* +Function + recvfrom + +Description + +Return + + +Author + Ahmed Ezzat + +Version + 1.0 + 2.0 9 April 2013 --> Add timeout for recv operation. + +Date + 5 June 2012 +*********************************************************************/ +sint16 recvfrom(SOCKET sock, void *pvRecvBuf, uint16 u16BufLen, uint32 u32Timeoutmsec) +{ + sint16 s16Ret = SOCK_ERR_NO_ERROR; + if((sock >= 0) && (pvRecvBuf != NULL) && (u16BufLen != 0) && (gastrSockets[sock].bIsUsed == 1)) + { + if(gastrSockets[sock].bIsUsed) + { + s16Ret = SOCK_ERR_NO_ERROR; + gastrSockets[sock].pu8UserBuffer = (uint8*)pvRecvBuf; + gastrSockets[sock].u16UserBufferSize = u16BufLen; + + if(!gastrSockets[sock].bIsRecvPending) + { + tstrRecvCmd strRecv; + + gastrSockets[sock].bIsRecvPending = 1; + + /* Check the timeout value. */ + if(u32Timeoutmsec == 0) + strRecv.u32Timeoutmsec = 0xFFFFFFFF; + else + strRecv.u32Timeoutmsec = NM_BSP_B_L_32(u32Timeoutmsec); + strRecv.sock = sock; + strRecv.u16SessionID = gastrSockets[sock].u16SessionID; + + s16Ret = SOCKET_REQUEST(SOCKET_CMD_RECVFROM, (uint8*)&strRecv, sizeof(tstrRecvCmd), NULL , 0, 0); + if(s16Ret != SOCK_ERR_NO_ERROR) + { + s16Ret = SOCK_ERR_BUFFER_FULL; + } + } + } + } + else + { + s16Ret = SOCK_ERR_INVALID_ARG; + } + return s16Ret; +} +/********************************************************************* +Function + nmi_inet_addr + +Description + +Return + Unsigned 32-bit integer representing the IP address in Network + byte order. + +Author + Ahmed Ezzat + +Version + 1.0 + +Date + 4 June 2012 +*********************************************************************/ +uint32 nmi_inet_addr(char *pcIpAddr) +{ + uint8 tmp; + uint32 u32IP = 0; + uint8 au8IP[4]; + uint8 c; + uint8 i, j; + + tmp = 0; + + for(i = 0; i < 4; ++i) + { + j = 0; + do + { + c = *pcIpAddr; + ++j; + if(j > 4) + { + return 0; + } + if(c == '.' || c == 0) + { + au8IP[i] = tmp; + tmp = 0; + } + else if(c >= '0' && c <= '9') + { + tmp = (tmp * 10) + (c - '0'); + } + else + { + return 0; + } + ++pcIpAddr; + } while(c != '.' && c != 0); + } + m2m_memcpy((uint8*)&u32IP, au8IP, 4); + return u32IP; +} +/********************************************************************* +Function + gethostbyname + +Description + +Return + None. + +Author + Ahmed Ezzat + +Version + 1.0 + +Date + 4 June 2012 +*********************************************************************/ +sint8 gethostbyname(uint8 * pcHostName) +{ + sint8 s8Err = SOCK_ERR_INVALID_ARG; + uint8 u8HostNameSize = (uint8)m2m_strlen(pcHostName); + if(u8HostNameSize <= HOSTNAME_MAX_SIZE) + { + s8Err = SOCKET_REQUEST(SOCKET_CMD_DNS_RESOLVE, (uint8*)pcHostName, u8HostNameSize + 1, NULL,0, 0); + } + return s8Err; +} +/********************************************************************* +Function + setsockopt + +Description + +Return + None. + +Author + Abdelrahman Diab + +Version + 1.0 + +Date + 9 September 2014 +*********************************************************************/ +static sint8 sslSetSockOpt(SOCKET sock, uint8 u8Opt, const void *pvOptVal, uint16 u16OptLen) +{ + sint8 s8Ret = SOCK_ERR_INVALID_ARG; + if(sock < TCP_SOCK_MAX) + { + if(gastrSockets[sock].u8SSLFlags & SSL_FLAGS_ACTIVE) + { + if(u8Opt == SO_SSL_BYPASS_X509_VERIF) + { + int optVal = *((int*)pvOptVal); + if(optVal) + { + gastrSockets[sock].u8SSLFlags |= SSL_FLAGS_BYPASS_X509; + } + else + { + gastrSockets[sock].u8SSLFlags &= ~SSL_FLAGS_BYPASS_X509; + } + s8Ret = SOCK_ERR_NO_ERROR; + } + else if(u8Opt == SO_SSL_ENABLE_SESSION_CACHING) + { + int optVal = *((int*)pvOptVal); + if(optVal) + { + gastrSockets[sock].u8SSLFlags |= SSL_FLAGS_CACHE_SESSION; + } + else + { + gastrSockets[sock].u8SSLFlags &= ~SSL_FLAGS_CACHE_SESSION; + } + s8Ret = SOCK_ERR_NO_ERROR; + } + else if(u8Opt == SO_SSL_ENABLE_SNI_VALIDATION) + { + int optVal = *((int*)pvOptVal); + if(optVal) + { + gastrSockets[sock].u8SSLFlags |= SSL_FLAGS_CHECK_SNI; + } + else + { + gastrSockets[sock].u8SSLFlags &= ~SSL_FLAGS_CHECK_SNI; + } + s8Ret = SOCK_ERR_NO_ERROR; + } + else if(u8Opt == SO_SSL_SNI) + { + if(u16OptLen < HOSTNAME_MAX_SIZE) + { + uint8 *pu8SNI = (uint8*)pvOptVal; + tstrSSLSetSockOptCmd strCmd; + + strCmd.sock = sock; + strCmd.u16SessionID = gastrSockets[sock].u16SessionID; + strCmd.u8Option = u8Opt; + strCmd.u32OptLen = u16OptLen; + m2m_memcpy(strCmd.au8OptVal, pu8SNI, HOSTNAME_MAX_SIZE); + + if(SOCKET_REQUEST(SOCKET_CMD_SSL_SET_SOCK_OPT, (uint8*)&strCmd, sizeof(tstrSSLSetSockOptCmd), + 0, 0, 0) == M2M_ERR_MEM_ALLOC) + { + s8Ret = SOCKET_REQUEST(SOCKET_CMD_SSL_SET_SOCK_OPT | M2M_REQ_DATA_PKT, + (uint8*)&strCmd, sizeof(tstrSSLSetSockOptCmd), 0, 0, 0); + } + s8Ret = SOCK_ERR_NO_ERROR; + } + else + { + M2M_ERR("SNI Exceeds Max Length\n"); + } + } + else + { + M2M_ERR("Unknown SSL Socket Option %d\n",u8Opt); + } + } + else + { + M2M_ERR("Not SSL Socket\n"); + } + } + return s8Ret; +} +/********************************************************************* +Function + setsockopt + +Description + +Return + None. + +Author + Abdelrahman Diab + +Version + 1.0 + +Date + 9 September 2014 +*********************************************************************/ +sint8 setsockopt(SOCKET sock, uint8 u8Level, uint8 option_name, + const void *option_value, uint16 u16OptionLen) +{ + sint8 s8Ret = SOCK_ERR_INVALID_ARG; + if((sock >= 0) && (option_value != NULL) && (gastrSockets[sock].bIsUsed == 1)) + { + if(u8Level == SOL_SSL_SOCKET) + { + s8Ret = sslSetSockOpt(sock, option_name, option_value, u16OptionLen); + } + else + { + uint8 u8Cmd = SOCKET_CMD_SET_SOCKET_OPTION; + tstrSetSocketOptCmd strSetSockOpt; + strSetSockOpt.u8Option=option_name; + strSetSockOpt.sock = sock; + strSetSockOpt.u32OptionValue = *(uint32*)option_value; + strSetSockOpt.u16SessionID = gastrSockets[sock].u16SessionID; + + s8Ret = SOCKET_REQUEST(u8Cmd, (uint8*)&strSetSockOpt, sizeof(tstrSetSocketOptCmd), NULL,0, 0); + if(s8Ret != SOCK_ERR_NO_ERROR) + { + s8Ret = SOCK_ERR_INVALID; + } + } + } + return s8Ret; +} +/********************************************************************* +Function + getsockopt + +Description + +Return + None. + +Author + Ahmed Ezzat + +Version + 1.0 + +Date + 24 August 2014 +*********************************************************************/ +sint8 getsockopt(SOCKET sock, uint8 u8Level, uint8 u8OptName, const void *pvOptValue, uint8* pu8OptLen) +{ + /* TBD */ + return M2M_SUCCESS; +} +/********************************************************************* +Function + m2m_ping_req + +Description + Send Ping request. + +Return + +Author + Ahmed Ezzat + +Version + 1.0 + +Date + 4 June 2015 +*********************************************************************/ +sint8 m2m_ping_req(uint32 u32DstIP, uint8 u8TTL, tpfPingCb fpPingCb) +{ + sint8 s8Ret = M2M_ERR_INVALID_ARG; + + if((u32DstIP != 0) && (fpPingCb != NULL)) + { + tstrPingCmd strPingCmd; + + strPingCmd.u16PingCount = 1; + strPingCmd.u32DestIPAddr = u32DstIP; + strPingCmd.u32CmdPrivate = (uint32)fpPingCb; + strPingCmd.u8TTL = u8TTL; + + s8Ret = SOCKET_REQUEST(SOCKET_CMD_PING, (uint8*)&strPingCmd, sizeof(tstrPingCmd), NULL, 0, 0); + } + return s8Ret; +} +/********************************************************************* +Function + sslEnableCertExpirationCheck + +Description + Enable/Disable TLS Certificate Expiration Check. + +Return + +Author + Ahmed Ezzat + +Version + 1.0 + +Date + +*********************************************************************/ +sint8 sslEnableCertExpirationCheck(tenuSslCertExpSettings enuValidationSetting) +{ + tstrSslCertExpSettings strSettings; + strSettings.u32CertExpValidationOpt = (uint32)enuValidationSetting; + return SOCKET_REQUEST(SOCKET_CMD_SSL_EXP_CHECK, (uint8*)&strSettings, sizeof(tstrSslCertExpSettings), NULL, 0, 0); +} \ No newline at end of file diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/socket/source/socket_internal.h b/ext/hal/atmel/asf/common/components/wifi/winc1500/socket/source/socket_internal.h new file mode 100644 index 0000000000000..cb21f591f842e --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/socket/source/socket_internal.h @@ -0,0 +1,68 @@ +/** + * + * \file + * + * \brief BSD compatible socket interface internal types. + * + * Copyright (c) 2016-2017 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ +#ifndef __SOCKET_INTERNAL_H__ +#define __SOCKET_INTERNAL_H__ + + +#ifdef __cplusplus +extern "C" { +#endif + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +INCLUDES +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ + +#include "socket/include/socket.h" +#include "socket/include/m2m_socket_host_if.h" + + +/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +FUNCTION PROTOTYPES +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ + +NMI_API void Socket_ReadSocketData(SOCKET sock, tstrSocketRecvMsg *pstrRecv,uint8 u8SocketMsg, + uint32 u32StartAddress,uint16 u16ReadCount); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __SOCKET_H__ */ diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/spi_flash/include/spi_flash.h b/ext/hal/atmel/asf/common/components/wifi/winc1500/spi_flash/include/spi_flash.h new file mode 100644 index 0000000000000..74b3a1a18be00 --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/spi_flash/include/spi_flash.h @@ -0,0 +1,222 @@ +/** + * + * \file + * + * \brief WINC1500 SPI Flash. + * + * Copyright (c) 2016-2017 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + +/** \defgroup SPIFLASH Spi Flash + * @file spi_flash.h + * @brief This file describe SPI flash APIs, how to use it and limitations with each one. + * @section Example + * This example illustrates a complete guide of how to use these APIs. + * @code{.c} + #include "spi_flash.h" + + #define DATA_TO_REPLACE "THIS IS A NEW SECTOR IN FLASH" + + int main() + { + uint8 au8FlashContent[FLASH_SECTOR_SZ] = {0}; + uint32 u32FlashTotalSize = 0; + uint32 u32FlashOffset = 0; + + ret = m2m_wifi_download_mode(); + if(M2M_SUCCESS != ret) + { + printf("Unable to enter download mode\r\n"); + } + else + { + u32FlashTotalSize = spi_flash_get_size(); + } + + while((u32FlashTotalSize > u32FlashOffset) && (M2M_SUCCESS == ret)) + { + ret = spi_flash_read(au8FlashContent, u32FlashOffset, FLASH_SECTOR_SZ); + if(M2M_SUCCESS != ret) + { + printf("Unable to read SPI sector\r\n"); + break; + } + memcpy(au8FlashContent, DATA_TO_REPLACE, strlen(DATA_TO_REPLACE)); + + ret = spi_flash_erase(u32FlashOffset, FLASH_SECTOR_SZ); + if(M2M_SUCCESS != ret) + { + printf("Unable to erase SPI sector\r\n"); + break; + } + + ret = spi_flash_write(au8FlashContent, u32FlashOffset, FLASH_SECTOR_SZ); + if(M2M_SUCCESS != ret) + { + printf("Unable to write SPI sector\r\n"); + break; + } + u32FlashOffset += FLASH_SECTOR_SZ; + } + + if(M2M_SUCCESS == ret) + { + printf("Successful operations\r\n"); + } + else + { + printf("Failed operations\r\n"); + } + + while(1); + return M2M_SUCCESS; + } + * @endcode + */ + +#ifndef __SPI_FLASH_H__ +#define __SPI_FLASH_H__ +#include "common/include/nm_common.h" +#include "bus_wrapper/include/nm_bus_wrapper.h" +#include "driver/source/nmbus.h" +#include "driver/source/nmasic.h" + +/** + * @fn spi_flash_enable + * @brief Enable spi flash operations + * @version 1.0 + */ +sint8 spi_flash_enable(uint8 enable); +/** \defgroup SPIFLASHAPI Function + * @ingroup SPIFLASH + */ + + /** @defgroup SPiFlashGetFn spi_flash_get_size + * @ingroup SPIFLASHAPI + */ + /**@{*/ +/*! + * @fn uint32 spi_flash_get_size(void); + * @brief Returns with \ref uint32 value which is total flash size\n + * @note Returned value in Mb (Mega Bit). + * @return SPI flash size in case of success and a ZERO value in case of failure. + */ +uint32 spi_flash_get_size(void); + /**@}*/ + + /** @defgroup SPiFlashRead spi_flash_read + * @ingroup SPIFLASHAPI + */ + /**@{*/ +/*! + * @fn sint8 spi_flash_read(uint8 *, uint32, uint32); + * @brief Read a specified portion of data from SPI Flash.\n + * @param [out] pu8Buf + * Pointer to data buffer which will fill in with data in case of successful operation. + * @param [in] u32Addr + * Address (Offset) to read from at the SPI flash. + * @param [in] u32Sz + * Total size of data to be read in bytes + * @warning + * - Address (offset) plus size of data must not exceed flash size.\n + * - No firmware is required for reading from SPI flash.\n + * - In case of there is a running firmware, it is required to pause your firmware first + * before any trial to access SPI flash to avoid any racing between host and running firmware on bus using + * @ref m2m_wifi_download_mode + * @note + * - It is blocking function\n + * @sa m2m_wifi_download_mode, spi_flash_get_size + * @return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. + */ +sint8 spi_flash_read(uint8 *pu8Buf, uint32 u32Addr, uint32 u32Sz); + /**@}*/ + + /** @defgroup SPiFlashWrite spi_flash_write + * @ingroup SPIFLASHAPI + */ + /**@{*/ +/*! + * @fn sint8 spi_flash_write(uint8 *, uint32, uint32); + * @brief Write a specified portion of data to SPI Flash.\n + * @param [in] pu8Buf + * Pointer to data buffer which contains the required to be written. + * @param [in] u32Offset + * Address (Offset) to write at the SPI flash. + * @param [in] u32Sz + * Total number of size of data bytes + * @note + * - It is blocking function\n + * - It is user's responsibility to verify that data has been written successfully + * by reading data again and compare it with the original. + * @warning + * - Address (offset) plus size of data must not exceed flash size.\n + * - No firmware is required for writing to SPI flash.\n + * - In case of there is a running firmware, it is required to pause your firmware first + * before any trial to access SPI flash to avoid any racing between host and running firmware on bus using + * @ref m2m_wifi_download_mode. + * - Before writing to any section, it is required to erase it first. + * @sa m2m_wifi_download_mode, spi_flash_get_size, spi_flash_erase + * @return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. + + */ +sint8 spi_flash_write(uint8* pu8Buf, uint32 u32Offset, uint32 u32Sz); + /**@}*/ + + /** @defgroup SPiFlashErase spi_flash_erase + * @ingroup SPIFLASHAPI + */ + /**@{*/ +/*! + * @fn sint8 spi_flash_erase(uint32, uint32); + * @brief Erase a specified portion of SPI Flash.\n + * @param [in] u32Offset + * Address (Offset) to erase from the SPI flash. + * @param [in] u32Sz + * Size of SPI flash required to be erased. + * @note It is blocking function \n +* @warning +* - Address (offset) plus size of data must not exceed flash size.\n +* - No firmware is required for writing to SPI flash.\n + * - In case of there is a running firmware, it is required to pause your firmware first + * before any trial to access SPI flash to avoid any racing between host and running firmware on bus using + * @ref m2m_wifi_download_mode + * - It is blocking function\n + * @sa m2m_wifi_download_mode, spi_flash_get_size + * @return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise. + + */ +sint8 spi_flash_erase(uint32 u32Offset, uint32 u32Sz); + /**@}*/ +#endif //__SPI_FLASH_H__ diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/spi_flash/include/spi_flash_map.h b/ext/hal/atmel/asf/common/components/wifi/winc1500/spi_flash/include/spi_flash_map.h new file mode 100644 index 0000000000000..3b0da53d68dec --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/spi_flash/include/spi_flash_map.h @@ -0,0 +1,245 @@ +/** + * + * \file + * + * \brief WINC1500 SPI Flash. + * + * Copyright (c) 2016-2017 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + +/** +* @file spi_flash_map.h +* @brief This module contains spi flash CONTENT +* @author M.S.M +* @date 17 SEPT 2013 +* @version 1.0 +*/ +#ifndef __SPI_FLASH_MAP_H__ +#define __SPI_FLASH_MAP_H__ + +#define FLASH_MAP_VER_0 (0) +#define FLASH_MAP_VER_1 (1) +#define FLASH_MAP_VER_2 (2) +#define FLASH_MAP_VER_3 (3) + +#define FLASH_MAP_VERSION FLASH_MAP_VER_3 + +//#define DOWNLOAD_ROLLBACK +//#define OTA_GEN +#define _PROGRAM_POWER_SAVE_ + +/* =======*=======*=======*=======*======= + * General Sizes for Flash Memory + * =======*=======*=======*=======*======= + */ + +#define FLASH_START_ADDR (0UL) +/*! location :xxxK + * "S:xxxK" -means-> Size is :xxxK + */ + +/* + * Boot Firmware: which used to select which firmware to run + * + */ +#define M2M_BOOT_FIRMWARE_STARTING_ADDR (FLASH_START_ADDR) +#define M2M_BOOT_FIRMWARE_FLASH_SZ (FLASH_SECTOR_SZ) + +/* + * Control Section: which used by Boot firmware + * + */ +#define M2M_CONTROL_FLASH_OFFSET (M2M_BOOT_FIRMWARE_STARTING_ADDR + M2M_BOOT_FIRMWARE_FLASH_SZ) +#define M2M_CONTROL_FLASH_BKP_OFFSET (M2M_CONTROL_FLASH_OFFSET + FLASH_SECTOR_SZ) +#define M2M_CONTROL_FLASH_SEC_SZ (FLASH_SECTOR_SZ) +#define M2M_CONTROL_FLASH_TOTAL_SZ (FLASH_SECTOR_SZ * 2) + +/* + * LUT for PLL and TX Gain settings: + * + */ +#define M2M_PLL_FLASH_OFFSET (M2M_CONTROL_FLASH_OFFSET + M2M_CONTROL_FLASH_TOTAL_SZ) +#define M2M_PLL_FLASH_SZ (1024 * 1) +#define M2M_GAIN_FLASH_OFFSET (M2M_PLL_FLASH_OFFSET + M2M_PLL_FLASH_SZ) +#define M2M_GAIN_FLASH_SZ (M2M_CONFIG_SECT_TOTAL_SZ - M2M_PLL_FLASH_SZ) +#define M2M_CONFIG_SECT_TOTAL_SZ (FLASH_SECTOR_SZ) + +/* + * Certificate: + * + */ +#define M2M_TLS_ROOTCER_FLASH_OFFSET (M2M_PLL_FLASH_OFFSET + M2M_CONFIG_SECT_TOTAL_SZ) +#define M2M_TLS_ROOTCER_FLASH_SIZE (FLASH_SECTOR_SZ * 1) + +/* + * TLS Server Key Files + * + */ +#define M2M_TLS_SERVER_FLASH_OFFSET (M2M_TLS_ROOTCER_FLASH_OFFSET + M2M_TLS_ROOTCER_FLASH_SIZE) +#define M2M_TLS_SERVER_FLASH_SIZE (FLASH_SECTOR_SZ * 2) + +/* + * HTTP Files + * + */ +#define M2M_HTTP_MEM_FLASH_OFFSET (M2M_TLS_SERVER_FLASH_OFFSET + M2M_TLS_SERVER_FLASH_SIZE) +#define M2M_HTTP_MEM_FLASH_SZ (FLASH_SECTOR_SZ * 2) + +/* + * Saved Connection Parameters: + * + */ +#define M2M_CACHED_CONNS_FLASH_OFFSET (M2M_HTTP_MEM_FLASH_OFFSET + M2M_HTTP_MEM_FLASH_SZ) +#define M2M_CACHED_CONNS_FLASH_SZ (FLASH_SECTOR_SZ * 1) + +/* + * + * Common section size + */ + +#define M2M_COMMON_DATA_SEC \ + (\ + M2M_BOOT_FIRMWARE_FLASH_SZ + \ + M2M_CONTROL_FLASH_TOTAL_SZ + \ + M2M_CONFIG_SECT_TOTAL_SZ + \ + M2M_TLS_ROOTCER_FLASH_SIZE + \ + M2M_TLS_SERVER_FLASH_SIZE + \ + M2M_HTTP_MEM_FLASH_SZ + \ + M2M_CACHED_CONNS_FLASH_SZ \ + ) + +/* + * + * OTA image1 Offset + */ + +#define M2M_OTA_IMAGE1_OFFSET (M2M_CACHED_CONNS_FLASH_OFFSET + M2M_CACHED_CONNS_FLASH_SZ) +/* + * Firmware Offset + * + */ +#if (defined _FIRMWARE_)||(defined OTA_GEN) +#define M2M_FIRMWARE_FLASH_OFFSET (0UL) +#else +#if (defined DOWNLOAD_ROLLBACK) +#define M2M_FIRMWARE_FLASH_OFFSET (M2M_OTA_IMAGE2_OFFSET) +#else +#define M2M_FIRMWARE_FLASH_OFFSET (M2M_OTA_IMAGE1_OFFSET) +#endif +#endif +/* + * + * Firmware + */ +#define M2M_FIRMWARE_FLASH_SZ (236 * 1024UL) +/** + * + * OTA image Size + */ +#define OTA_IMAGE_SIZE (M2M_FIRMWARE_FLASH_SZ) +/** + * + * Flash Total size + */ +#define FLASH_IMAGE1_CONTENT_SZ (M2M_COMMON_DATA_SEC + OTA_IMAGE_SIZE) + +/** + * + * OTA image 2 offset + */ +#define M2M_OTA_IMAGE2_OFFSET (FLASH_IMAGE1_CONTENT_SZ) + +/* + * App(Cortus App 4M): App. which runs over firmware + * + */ +#define M2M_APP_4M_MEM_FLASH_SZ (FLASH_SECTOR_SZ * 16) +#define M2M_APP_4M_MEM_FLASH_OFFSET (FLASH_4M_TOTAL_SZ - M2M_APP_4M_MEM_FLASH_SZ) +#define M2M_APP_8M_MEM_FLASH_OFFSET (M2M_OTA_IMAGE2_OFFSET + OTA_IMAGE_SIZE) +#define M2M_APP_8M_MEM_FLASH_SZ (FLASH_SECTOR_SZ * 32) +#define M2M_APP_OTA_MEM_FLASH_OFFSET (M2M_APP_8M_MEM_FLASH_OFFSET + M2M_APP_8M_MEM_FLASH_SZ) + +/* Check if total size of content + * don't exceed total size of memory allowed + **/ +#if (M2M_COMMON_DATA_SEC + (OTA_IMAGE_SIZE *2)> FLASH_4M_TOTAL_SZ) +#error "Excced 4M Flash Size" +#endif /* (FLASH_CONTENT_SZ > FLASH_TOTAL_SZ) */ + + +#endif /* __SPI_FLASH_MAP_H__ */ diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/spi_flash/source/spi_flash.c b/ext/hal/atmel/asf/common/components/wifi/winc1500/spi_flash/source/spi_flash.c new file mode 100644 index 0000000000000..c5627628de89e --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/spi_flash/source/spi_flash.c @@ -0,0 +1,754 @@ +/** + * + * \file + * + * \brief WINC1500 SPI Flash. + * + * Copyright (c) 2016-2017 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + +#ifdef PROFILING +#include "windows.h" +#endif +#include "spi_flash/include/spi_flash.h" +#define DUMMY_REGISTER (0x1084) + +#define TIMEOUT (-1) /*MS*/ + +//#define DISABLE_UNSED_FLASH_FUNCTIONS + +#define FLASH_BLOCK_SIZE (32UL * 1024) +/*!> 16); + cmd[2] = (uint8)(u32FlashAdr >> 8); + cmd[3] = (uint8)(u32FlashAdr); + cmd[4] = 0xA5; + + ret += nm_write_reg(SPI_FLASH_DATA_CNT, u32Sz); + ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]|(cmd[1]<<8)|(cmd[2]<<16)|(cmd[3]<<24)); + ret += nm_write_reg(SPI_FLASH_BUF2, cmd[4]); + ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x1f); + ret += nm_write_reg(SPI_FLASH_DMA_ADDR, u32MemAdr); + ret += nm_write_reg(SPI_FLASH_CMD_CNT, 5 | (1<<7)); + do + { + ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&val); + if(M2M_SUCCESS != ret) break; + } + while(val != 1); + + return ret; +} + +/** +* @fn spi_flash_sector_erase +* @brief Erase sector (4KB) +* @param[IN] u32FlashAdr +* Any memory address within the sector +* @return Status of execution +* @note Compatible with MX25L6465E and should be working with other types +* @author M. Abdelmawla +* @version 1.0 +*/ +static sint8 spi_flash_sector_erase(uint32 u32FlashAdr) +{ + uint8 cmd[4]; + uint32 val = 0; + sint8 ret = M2M_SUCCESS; + + cmd[0] = 0x20; + cmd[1] = (uint8)(u32FlashAdr >> 16); + cmd[2] = (uint8)(u32FlashAdr >> 8); + cmd[3] = (uint8)(u32FlashAdr); + + ret += nm_write_reg(SPI_FLASH_DATA_CNT, 0); + ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]|(cmd[1]<<8)|(cmd[2]<<16)|(cmd[3]<<24)); + ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x0f); + ret += nm_write_reg(SPI_FLASH_DMA_ADDR, 0); + ret += nm_write_reg(SPI_FLASH_CMD_CNT, 4 | (1<<7)); + do + { + ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&val); + if(M2M_SUCCESS != ret) break; + } + while(val != 1); + + return ret; +} + +/** +* @fn spi_flash_write_enable +* @brief Send write enable command to SPI flash +* @return Status of execution +* @note Compatible with MX25L6465E and should be working with other types +* @author M. Abdelmawla +* @version 1.0 +*/ +static sint8 spi_flash_write_enable(void) +{ + uint8 cmd[1]; + uint32 val = 0; + sint8 ret = M2M_SUCCESS; + + cmd[0] = 0x06; + + ret += nm_write_reg(SPI_FLASH_DATA_CNT, 0); + ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]); + ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x01); + ret += nm_write_reg(SPI_FLASH_DMA_ADDR, 0); + ret += nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1<<7)); + do + { + ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&val); + if(M2M_SUCCESS != ret) break; + } + while(val != 1); + + return ret; +} + +/** +* @fn spi_flash_write_disable +* @brief Send write disable command to SPI flash +* @note Compatible with MX25L6465E and should be working with other types +* @author M. Abdelmawla +* @version 1.0 +*/ +static sint8 spi_flash_write_disable(void) +{ + uint8 cmd[1]; + uint32 val = 0; + sint8 ret = M2M_SUCCESS; + cmd[0] = 0x04; + + ret += nm_write_reg(SPI_FLASH_DATA_CNT, 0); + ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]); + ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x01); + ret += nm_write_reg(SPI_FLASH_DMA_ADDR, 0); + ret += nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1<<7)); + do + { + ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&val); + if(M2M_SUCCESS != ret) break; + } + while(val != 1); + + return ret; +} + +/** +* @fn spi_flash_page_program +* @brief Write data (less than page size) from cortus memory to SPI flash +* @param[IN] u32MemAdr +* Cortus data address. It must be set to its AHB access address +* @param[IN] u32FlashAdr +* Address to write to at the SPI flash +* @param[IN] u32Sz +* Data size +* @note Compatible with MX25L6465E and should be working with other types +* @author M. Abdelmawla +* @version 1.0 +*/ +static sint8 spi_flash_page_program(uint32 u32MemAdr, uint32 u32FlashAdr, uint32 u32Sz) +{ + uint8 cmd[4]; + uint32 val = 0; + sint8 ret = M2M_SUCCESS; + + cmd[0] = 0x02; + cmd[1] = (uint8)(u32FlashAdr >> 16); + cmd[2] = (uint8)(u32FlashAdr >> 8); + cmd[3] = (uint8)(u32FlashAdr); + + ret += nm_write_reg(SPI_FLASH_DATA_CNT, 0); + ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]|(cmd[1]<<8)|(cmd[2]<<16)|(cmd[3]<<24)); + ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x0f); + ret += nm_write_reg(SPI_FLASH_DMA_ADDR, u32MemAdr); + ret += nm_write_reg(SPI_FLASH_CMD_CNT, 4 | (1<<7) | ((u32Sz & 0xfffff) << 8)); + do + { + ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&val); + if(M2M_SUCCESS != ret) break; + } + while(val != 1); + + return ret; +} + +/** +* @fn spi_flash_read_internal +* @brief Read from data from SPI flash +* @param[OUT] pu8Buf +* Pointer to data buffer +* @param[IN] u32Addr +* Address to read from at the SPI flash +* @param[IN] u32Sz +* Data size +* @note Data size must be < 64KB (limitation imposed by the bus wrapper) +* @author M. Abdelmawla +* @version 1.0 +*/ +static sint8 spi_flash_read_internal(uint8 *pu8Buf, uint32 u32Addr, uint32 u32Sz) +{ + sint8 ret = M2M_SUCCESS; + /* read size must be < 64KB */ + ret = spi_flash_load_to_cortus_mem(HOST_SHARE_MEM_BASE, u32Addr, u32Sz); + if(M2M_SUCCESS != ret) goto ERR; + ret = nm_read_block(HOST_SHARE_MEM_BASE, pu8Buf, u32Sz); +ERR: + return ret; +} + +/** +* @fn spi_flash_pp +* @brief Program data of size less than a page (256 bytes) at the SPI flash +* @param[IN] u32Offset +* Address to write to at the SPI flash +* @param[IN] pu8Buf +* Pointer to data buffer +* @param[IN] u32Sz +* Data size +* @return Status of execution +* @author M. Abdelmawla +* @version 1.0 +*/ +static sint8 spi_flash_pp(uint32 u32Offset, uint8 *pu8Buf, uint16 u16Sz) +{ + sint8 ret = M2M_SUCCESS; + uint8 tmp; + spi_flash_write_enable(); + /* use shared packet memory as temp mem */ + ret += nm_write_block(HOST_SHARE_MEM_BASE, pu8Buf, u16Sz); + ret += spi_flash_page_program(HOST_SHARE_MEM_BASE, u32Offset, u16Sz); + ret += spi_flash_read_status_reg(&tmp); + do + { + if(ret != M2M_SUCCESS) goto ERR; + ret += spi_flash_read_status_reg(&tmp); + }while(tmp & 0x01); + ret += spi_flash_write_disable(); +ERR: + return ret; +} + +/** +* @fn spi_flash_rdid +* @brief Read SPI Flash ID +* @return SPI FLash ID +* @author M.S.M +* @version 1.0 +*/ +static uint32 spi_flash_rdid(void) +{ + unsigned char cmd[1]; + uint32 reg = 0; + uint32 cnt = 0; + sint8 ret = M2M_SUCCESS; + + cmd[0] = 0x9f; + + ret += nm_write_reg(SPI_FLASH_DATA_CNT, 4); + ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]); + ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x1); + ret += nm_write_reg(SPI_FLASH_DMA_ADDR, DUMMY_REGISTER); + ret += nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1<<7)); + do + { + ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)®); + if(M2M_SUCCESS != ret) break; + if(++cnt > 500) + { + ret = M2M_ERR_INIT; + break; + } + } + while(reg != 1); + reg = (M2M_SUCCESS == ret)?(nm_read_reg(DUMMY_REGISTER)):(0); + M2M_PRINT("Flash ID %x \n",(unsigned int)reg); + return reg; +} + +/** +* @fn spi_flash_unlock +* @brief Unlock SPI Flash +* @author M.S.M +* @version 1.0 +*/ +#if 0 +static void spi_flash_unlock(void) +{ + uint8 tmp; + tmp = spi_flash_read_security_reg(); + spi_flash_clear_security_flags(); + if(tmp & 0x80) + { + spi_flash_write_enable(); + spi_flash_gang_unblock(); + } +} +#endif +static void spi_flash_enter_low_power_mode(void) { + volatile unsigned long tmp; + unsigned char* cmd = (unsigned char*) &tmp; + + cmd[0] = 0xb9; + + nm_write_reg(SPI_FLASH_DATA_CNT, 0); + nm_write_reg(SPI_FLASH_BUF1, cmd[0]); + nm_write_reg(SPI_FLASH_BUF_DIR, 0x1); + nm_write_reg(SPI_FLASH_DMA_ADDR, 0); + nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1 << 7)); + while(nm_read_reg(SPI_FLASH_TR_DONE) != 1); +} + + +static void spi_flash_leave_low_power_mode(void) { + volatile unsigned long tmp; + unsigned char* cmd = (unsigned char*) &tmp; + + cmd[0] = 0xab; + + nm_write_reg(SPI_FLASH_DATA_CNT, 0); + nm_write_reg(SPI_FLASH_BUF1, cmd[0]); + nm_write_reg(SPI_FLASH_BUF_DIR, 0x1); + nm_write_reg(SPI_FLASH_DMA_ADDR, 0); + nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1 << 7)); + while(nm_read_reg(SPI_FLASH_TR_DONE) != 1); +} +/*********************************************/ +/* GLOBAL FUNCTIONS */ +/*********************************************/ +/** + * @fn spi_flash_enable + * @brief Enable spi flash operations + * @author M. Abdelmawla + * @version 1.0 + */ +sint8 spi_flash_enable(uint8 enable) +{ + sint8 s8Ret = M2M_SUCCESS; + if(REV(nmi_get_chipid()) >= REV_3A0) { + uint32 u32Val; + + /* Enable pinmux to SPI flash. */ + s8Ret = nm_read_reg_with_ret(0x1410, &u32Val); + if(s8Ret != M2M_SUCCESS) { + goto ERR1; + } + /* GPIO15/16/17/18 */ + u32Val &= ~((0x7777ul) << 12); + u32Val |= ((0x1111ul) << 12); + nm_write_reg(0x1410, u32Val); + if(enable) { + spi_flash_leave_low_power_mode(); + } else { + spi_flash_enter_low_power_mode(); + } + /* Disable pinmux to SPI flash to minimize leakage. */ + u32Val &= ~((0x7777ul) << 12); + u32Val |= ((0x0010ul) << 12); + nm_write_reg(0x1410, u32Val); + } +ERR1: + return s8Ret; +} +/** +* @fn spi_flash_read +* @brief Read from data from SPI flash +* @param[OUT] pu8Buf +* Pointer to data buffer +* @param[IN] u32offset +* Address to read from at the SPI flash +* @param[IN] u32Sz +* Data size +* @return Status of execution +* @note Data size is limited by the SPI flash size only +* @author M. Abdelmawla +* @version 1.0 +*/ +sint8 spi_flash_read(uint8 *pu8Buf, uint32 u32offset, uint32 u32Sz) +{ + sint8 ret = M2M_SUCCESS; + if(u32Sz > FLASH_BLOCK_SIZE) + { + do + { + ret = spi_flash_read_internal(pu8Buf, u32offset, FLASH_BLOCK_SIZE); + if(M2M_SUCCESS != ret) goto ERR; + u32Sz -= FLASH_BLOCK_SIZE; + u32offset += FLASH_BLOCK_SIZE; + pu8Buf += FLASH_BLOCK_SIZE; + } while(u32Sz > FLASH_BLOCK_SIZE); + } + + ret = spi_flash_read_internal(pu8Buf, u32offset, u32Sz); + +ERR: + return ret; +} + +/** +* @fn spi_flash_write +* @brief Proram SPI flash +* @param[IN] pu8Buf +* Pointer to data buffer +* @param[IN] u32Offset +* Address to write to at the SPI flash +* @param[IN] u32Sz +* Data size +* @return Status of execution +* @author M. Abdelmawla +* @version 1.0 +*/ +sint8 spi_flash_write(uint8* pu8Buf, uint32 u32Offset, uint32 u32Sz) +{ +#ifdef PROFILING + uint32 t1 = 0; + uint32 percent =0; + uint32 tpercent =0; +#endif + sint8 ret = M2M_SUCCESS; + uint32 u32wsz; + uint32 u32off; + uint32 u32Blksz; + u32Blksz = FLASH_PAGE_SZ; + u32off = u32Offset % u32Blksz; +#ifdef PROFILING + tpercent = (u32Sz/u32Blksz)+((u32Sz%u32Blksz)>0); + t1 = GetTickCount(); + M2M_PRINT(">Start programming...\r\n"); +#endif + if(u32Sz<=0) + { + M2M_ERR("Data size = %d",(int)u32Sz); + ret = M2M_ERR_FAIL; + goto ERR; + } + + if (u32off)/*first part of data in the address page*/ + { + u32wsz = u32Blksz - u32off; + if(spi_flash_pp(u32Offset, pu8Buf, (uint16)BSP_MIN(u32Sz, u32wsz))!=M2M_SUCCESS) + { + ret = M2M_ERR_FAIL; + goto ERR; + } + if (u32Sz < u32wsz) goto EXIT; + pu8Buf += u32wsz; + u32Offset += u32wsz; + u32Sz -= u32wsz; + } + while (u32Sz > 0) + { + u32wsz = BSP_MIN(u32Sz, u32Blksz); + + /*write complete page or the remaining data*/ + if(spi_flash_pp(u32Offset, pu8Buf, (uint16)u32wsz)!=M2M_SUCCESS) + { + ret = M2M_ERR_FAIL; + goto ERR; + } + pu8Buf += u32wsz; + u32Offset += u32wsz; + u32Sz -= u32wsz; +#ifdef PROFILING + percent++; + printf("\r>Complete Percentage = %d%%.\r",((percent*100)/tpercent)); +#endif + } +EXIT: +#ifdef PROFILING + M2M_PRINT("\rDone\t\t\t\t\t\t"); + M2M_PRINT("\n#Programming time = %f sec\n\r",(GetTickCount() - t1)/1000.0); +#endif +ERR: + return ret; +} + +/** +* @fn spi_flash_erase +* @brief Erase from data from SPI flash +* @param[IN] u32Offset +* Address to write to at the SPI flash +* @param[IN] u32Sz +* Data size +* @return Status of execution +* @note Data size is limited by the SPI flash size only +* @author M. Abdelmawla +* @version 1.0 +*/ +sint8 spi_flash_erase(uint32 u32Offset, uint32 u32Sz) +{ + uint32 i = 0; + sint8 ret = M2M_SUCCESS; + uint8 tmp = 0; +#ifdef PROFILING + uint32 t; + t = GetTickCount(); +#endif + M2M_PRINT("\r\n>Start erasing...\r\n"); + for(i = u32Offset; i < (u32Sz +u32Offset); i += (16*FLASH_PAGE_SZ)) + { + ret += spi_flash_write_enable(); + ret += spi_flash_read_status_reg(&tmp); + ret += spi_flash_sector_erase(i + 10); + ret += spi_flash_read_status_reg(&tmp); + do + { + if(ret != M2M_SUCCESS) goto ERR; + ret += spi_flash_read_status_reg(&tmp); + }while(tmp & 0x01); + + } + M2M_PRINT("Done\r\n"); +#ifdef PROFILING + M2M_PRINT("#Erase time = %f sec\n", (GetTickCount()-t)/1000.0); +#endif +ERR: + return ret; +} + +/** +* @fn spi_flash_get_size +* @brief Get size of SPI Flash +* @return Size of Flash +* @author M.S.M +* @version 1.0 +*/ +uint32 spi_flash_get_size(void) +{ + uint32 u32FlashId = 0, u32FlashPwr = 0; + static uint32 gu32InernalFlashSize= 0; + + if(!gu32InernalFlashSize) + { + u32FlashId = spi_flash_rdid();//spi_flash_probe(); + if(u32FlashId != 0xffffffff) + { + /*flash size is the third byte from the FLASH RDID*/ + u32FlashPwr = ((u32FlashId>>16)&0xff) - 0x11; /*2MBIT is the min*/ + /*That number power 2 to get the flash size*/ + gu32InernalFlashSize = 1< Date: Wed, 3 May 2017 09:09:29 +0200 Subject: [PATCH 02/13] drivers/wifi: Add winc1500 WiFi driver Adding support for WINC1500 WiFi chip. It introduces the wifi drivers sub-directory. It provides a Full-MAC for 802.11 and an offloaded network stack as well. The driver uses Atmel's winc1500 HAL. Signed-off-by: Dario Pennisi Signed-off-by: Anas Nashif Signed-off-by: Massimiliano Agneni Signed-off-by: Tomasz Bursztyka --- drivers/wifi/CMakeLists.txt | 9 + drivers/wifi/Kconfig | 2 + drivers/wifi/Kconfig.winc1500 | 62 ++ drivers/wifi/wifi_winc1500.c | 924 ++++++++++++++++++ drivers/wifi/wifi_winc1500_config.h | 66 ++ drivers/wifi/wifi_winc1500_nm_bsp.c | 98 ++ drivers/wifi/wifi_winc1500_nm_bsp_internal.h | 33 + drivers/wifi/wifi_winc1500_nm_bus_wrapper.c | 175 ++++ .../winc1500/bsp/include/nm_bsp_internal.h | 4 +- 9 files changed, 1372 insertions(+), 1 deletion(-) create mode 100644 drivers/wifi/CMakeLists.txt create mode 100644 drivers/wifi/Kconfig.winc1500 create mode 100644 drivers/wifi/wifi_winc1500.c create mode 100644 drivers/wifi/wifi_winc1500_config.h create mode 100644 drivers/wifi/wifi_winc1500_nm_bsp.c create mode 100644 drivers/wifi/wifi_winc1500_nm_bsp_internal.h create mode 100644 drivers/wifi/wifi_winc1500_nm_bus_wrapper.c diff --git a/drivers/wifi/CMakeLists.txt b/drivers/wifi/CMakeLists.txt new file mode 100644 index 0000000000000..a97b419ee23ab --- /dev/null +++ b/drivers/wifi/CMakeLists.txt @@ -0,0 +1,9 @@ +if(CONFIG_WIFI_WINC1500) + zephyr_include_directories(./) + + zephyr_sources( + wifi_winc1500_nm_bsp.c + wifi_winc1500_nm_bus_wrapper.c + wifi_winc1500.c + ) +endif() diff --git a/drivers/wifi/Kconfig b/drivers/wifi/Kconfig index 5d11c973ad0e4..731e684726e1b 100644 --- a/drivers/wifi/Kconfig +++ b/drivers/wifi/Kconfig @@ -43,4 +43,6 @@ config WIFI_OFFLOAD help Enable support for Full-MAC WiFi devices. +source "drivers/wifi/Kconfig.winc1500" + endif # WIFI diff --git a/drivers/wifi/Kconfig.winc1500 b/drivers/wifi/Kconfig.winc1500 new file mode 100644 index 0000000000000..488ca78a8796d --- /dev/null +++ b/drivers/wifi/Kconfig.winc1500 @@ -0,0 +1,62 @@ +# Kconfig - Atmel WINC1500 WiFi driver options + +# +# Copyright (c) 2015 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +# + +menuconfig WIFI_WINC1500 + bool "WINC1500 driver support" + default n + select ATMEL_WINC1500 + +if WIFI_WINC1500 + +config WIFI_WINC1500_NAME + string "Driver name" + default "WINC1500" + +config WIFI_WINC1500_SPI_DRV_NAME + string "SPI device where WINC1500 is connected" + default "SPI_1" + help + Specify the device name of the SPI device to which WINC1500 is + connected. + +config WIFI_WINC1500_SPI_SLAVE + int "SPI Slave Select where WINC1500 is connected" + default 1 + help + Specify the slave select pin of the SPI to which WINC1500 is + connected. + +config WIFI_WINC1500_SPI_FREQ + int "SPI frequency to use with WINC1500" + default 4 + help + SPI frequency to use with WINC1500 + +# TODO GPIO + +config WIFI_WINC1500_SSID + string "SSID the chip shall try to connect to" + default "" + help + Set the SSID you want the chip to connect to. Note: only WPA PSK + based AP is supported. Test purpose only, a full featured interface + will be used at some point for more flexible configuration. + +config WIFI_WINC1500_SSID_LENGTH + int "Length of the SSID (do not count the \0)" + default 0 + help + SSID length, without counting the terminal character '\0' + +config WIFI_WINC1500_PSK + string "Pre-Shared Key (human readable)" + default "" + help + Set the PSK for the given SSID. + +endif # WIFI_WINC1500 diff --git a/drivers/wifi/wifi_winc1500.c b/drivers/wifi/wifi_winc1500.c new file mode 100644 index 0000000000000..bb1a935698153 --- /dev/null +++ b/drivers/wifi/wifi_winc1500.c @@ -0,0 +1,924 @@ +/** + * Copyright (c) 2017 IpTronix + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define SYS_LOG_LEVEL CONFIG_SYS_LOG_WIFI_LEVEL +#define SYS_LOG_DOMAIN "dev/winc1500" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* We do not need + * It seems there is a bug in ASF side: if OS is already defining sockaddr + * and all, ASF will not need to define it. Unfortunately its socket.h does + * but also defines some NM API functions there (??), so we need to redefine + * those here. + */ +#define __SOCKET_H__ +#define HOSTNAME_MAX_SIZE (64) + +#include +#include + +NMI_API void socketInit(void); +typedef void (*tpfAppSocketCb) (SOCKET sock, uint8 u8Msg, void *pvMsg); +typedef void (*tpfAppResolveCb) (uint8 *pu8DomainName, uint32 u32ServerIP); +NMI_API void registerSocketCallback(tpfAppSocketCb socket_cb, + tpfAppResolveCb resolve_cb); +NMI_API SOCKET socket(uint16 u16Domain, uint8 u8Type, uint8 u8Flags); +NMI_API sint8 bind(SOCKET sock, struct sockaddr *pstrAddr, uint8 u8AddrLen); +NMI_API sint8 listen(SOCKET sock, uint8 backlog); +NMI_API sint8 accept(SOCKET sock, struct sockaddr *addr, uint8 *addrlen); +NMI_API sint8 connect(SOCKET sock, struct sockaddr *pstrAddr, uint8 u8AddrLen); +NMI_API sint16 recv(SOCKET sock, void *pvRecvBuf, + uint16 u16BufLen, uint32 u32Timeoutmsec); +NMI_API sint16 send(SOCKET sock, void *pvSendBuffer, + uint16 u16SendLength, uint16 u16Flags); +NMI_API sint16 sendto(SOCKET sock, void *pvSendBuffer, + uint16 u16SendLength, uint16 flags, + struct sockaddr *pstrDestAddr, uint8 u8AddrLen); + +enum socket_errors { + SOCK_ERR_NO_ERROR = 0, + SOCK_ERR_INVALID_ADDRESS = -1, + SOCK_ERR_ADDR_ALREADY_IN_USE = -2, + SOCK_ERR_MAX_TCP_SOCK = -3, + SOCK_ERR_MAX_UDP_SOCK = -4, + SOCK_ERR_INVALID_ARG = -6, + SOCK_ERR_MAX_LISTEN_SOCK = -7, + SOCK_ERR_INVALID = -9, + SOCK_ERR_ADDR_IS_REQUIRED = -11, + SOCK_ERR_CONN_ABORTED = -12, + SOCK_ERR_TIMEOUT = -13, + SOCK_ERR_BUFFER_FULL = -14, +}; + +enum socket_messages { + SOCKET_MSG_BIND = 1, + SOCKET_MSG_LISTEN, + SOCKET_MSG_DNS_RESOLVE, + SOCKET_MSG_ACCEPT, + SOCKET_MSG_CONNECT, + SOCKET_MSG_RECV, + SOCKET_MSG_SEND, + SOCKET_MSG_SENDTO, + SOCKET_MSG_RECVFROM, +}; + +typedef struct { + sint8 status; +} tstrSocketBindMsg; + +typedef struct { + sint8 status; +} tstrSocketListenMsg; + +typedef struct { + SOCKET sock; + struct sockaddr_in strAddr; +} tstrSocketAcceptMsg; + +typedef struct { + SOCKET sock; + sint8 s8Error; +} tstrSocketConnectMsg; + +typedef struct { + uint8 *pu8Buffer; + sint16 s16BufferSize; + uint16 u16RemainingSize; + struct sockaddr_in strRemoteAddr; +} tstrSocketRecvMsg; + +#include +#include + +#ifndef CONFIG_WINC1500_THREAD_STACK_SIZE +#define CONFIG_WINC1500_THREAD_STACK_SIZE 5000 +#endif +#ifndef CONFIG_WINC1500_THREAD_PRIO +#define CONFIG_WINC1500_THREAD_PRIO 2 +#endif + +#ifndef CONFIG_WINC1500_BUF_CTR +#define CONFIG_WINC1500_BUF_CTR 1 +#endif +#ifndef CONFIG_WINC1500_MAX_PACKET_SIZE +#define CONFIG_WINC1500_MAX_PACKET_SIZE 1500 +#endif +#ifndef CONFIG_OFFLOAD_MAX_SOCKETS +#define CONFIG_OFFLOAD_MAX_SOCKETS 2 +#endif + +#define WINC1500_BIND_TIMEOUT 500 +#define WINC1500_LISTEN_TIMEOUT 500 + +NET_BUF_POOL_DEFINE(winc1500_tx_pool, CONFIG_WINC1500_BUF_CTR, + CONFIG_WINC1500_MAX_PACKET_SIZE, 0, NULL); +NET_BUF_POOL_DEFINE(winc1500_rx_pool, CONFIG_WINC1500_BUF_CTR, + CONFIG_WINC1500_MAX_PACKET_SIZE, 0, NULL); + +K_THREAD_STACK_MEMBER(winc1500_stack, CONFIG_WINC1500_THREAD_STACK_SIZE); +struct k_thread winc1500_thread_data; + +struct socket_data { + struct net_context *context; + net_context_connect_cb_t connect_cb; + net_tcp_accept_cb_t accept_cb; + net_context_send_cb_t send_cb; + net_context_recv_cb_t recv_cb; + void *connect_user_data; + void *send_user_data; + void *recv_user_data; + void *accept_user_data; + struct net_pkt *rx_pkt; + struct net_buf *pkt_buf; + int ret_code; + struct k_sem wait_sem; +}; + +struct winc1500_data { + struct socket_data socket_data[CONFIG_OFFLOAD_MAX_SOCKETS]; + struct net_if *iface; + unsigned char mac[6]; +}; + +static struct winc1500_data w1500_data; + +#if (SYS_LOG_LEVEL > SYS_LOG_LEVEL_OFF) + +static char *socket_error_string(s8_t err) +{ + switch (err) { + case SOCK_ERR_NO_ERROR: + return "Successful socket operation"; + case SOCK_ERR_INVALID_ADDRESS: + return "Socket address is invalid." + "The socket operation cannot be completed successfully" + " without specifying a specific address. " + "For example: bind is called without specifying" + " a port number"; + case SOCK_ERR_ADDR_ALREADY_IN_USE: + return "Socket operation cannot bind on the given address." + " With socket operations, only one IP address per " + "socket is permitted. Any attempt for a new socket " + "to bind with an IP address already bound to another " + "open socket, will return the following error code. " + "States that bind operation failed."; + case SOCK_ERR_MAX_TCP_SOCK: + return "Exceeded the maximum number of TCP sockets." + "A maximum number of TCP sockets opened simultaneously" + " is defined through TCP_SOCK_MAX. It is not permitted" + " to exceed that number at socket creation." + " Identifies that @ref socket operation failed."; + case SOCK_ERR_MAX_UDP_SOCK: + return "Exceeded the maximum number of UDP sockets." + "A maximum number of UDP sockets opened simultaneously" + " is defined through UDP_SOCK_MAX. It is not permitted" + " to exceed that number at socket creation." + " Identifies that socket operation failed"; + case SOCK_ERR_INVALID_ARG: + return "An invalid argument is passed to a function."; + case SOCK_ERR_MAX_LISTEN_SOCK: + return "Exceeded the maximum number of TCP passive listening " + "sockets. Identifies Identifies that listen operation" + " failed."; + case SOCK_ERR_INVALID: + return "The requested socket operation is not valid in the " + "current socket state. For example: @ref accept is " + "called on a TCP socket before bind or listen."; + case SOCK_ERR_ADDR_IS_REQUIRED: + return "Destination address is required. Failure to provide " + "the socket address required for the socket operation " + "to be completed. It is generated as an error to the " + "sendto function when the address required to send the" + " data to is not known."; + case SOCK_ERR_CONN_ABORTED: + return "The socket is closed by the peer. The local socket is " + "also closed."; + case SOCK_ERR_TIMEOUT: + return "The socket pending operation has timedout."; + case SOCK_ERR_BUFFER_FULL: + return "No buffer space available to be used for the requested" + " socket operation."; + default: + return "Unknown"; + } +} + +static char *wifi_cb_msg_2_str(u8_t message_type) +{ + switch (message_type) { + case M2M_WIFI_RESP_CURRENT_RSSI: + return "M2M_WIFI_RESP_CURRENT_RSSI"; + case M2M_WIFI_REQ_WPS: + return "M2M_WIFI_REQ_WPS"; + case M2M_WIFI_RESP_IP_CONFIGURED: + return "M2M_WIFI_RESP_IP_CONFIGURED"; + case M2M_WIFI_RESP_IP_CONFLICT: + return "M2M_WIFI_RESP_IP_CONFLICT"; + case M2M_WIFI_RESP_CLIENT_INFO: + return "M2M_WIFI_RESP_CLIENT_INFO"; + + case M2M_WIFI_RESP_GET_SYS_TIME: + return "M2M_WIFI_RESP_GET_SYS_TIME"; + case M2M_WIFI_REQ_SEND_ETHERNET_PACKET: + return "M2M_WIFI_REQ_SEND_ETHERNET_PACKET"; + case M2M_WIFI_RESP_ETHERNET_RX_PACKET: + return "M2M_WIFI_RESP_ETHERNET_RX_PACKET"; + + case M2M_WIFI_RESP_CON_STATE_CHANGED: + return "M2M_WIFI_RESP_CON_STATE_CHANGED"; + case M2M_WIFI_REQ_DHCP_CONF: + return "Response indicating that IP address was obtained."; + case M2M_WIFI_RESP_SCAN_DONE: + return "M2M_WIFI_RESP_SCAN_DONE"; + case M2M_WIFI_RESP_SCAN_RESULT: + return "M2M_WIFI_RESP_SCAN_RESULT"; + case M2M_WIFI_RESP_PROVISION_INFO: + return "M2M_WIFI_RESP_PROVISION_INFO"; + default: + return "UNKNOWN"; + } +} + +static char *socket_message_to_string(u8_t message) +{ + switch (message) { + case SOCKET_MSG_BIND: + return "Bind socket event."; + case SOCKET_MSG_LISTEN: + return "Listen socket event."; + case SOCKET_MSG_DNS_RESOLVE: + return "DNS Resolution event."; + case SOCKET_MSG_ACCEPT: + return "Accept socket event."; + case SOCKET_MSG_CONNECT: + return "Connect socket event."; + case SOCKET_MSG_RECV: + return "Receive socket event."; + case SOCKET_MSG_SEND: + return "Send socket event."; + case SOCKET_MSG_SENDTO: + return "Sendto socket event."; + case SOCKET_MSG_RECVFROM: + return "Recvfrom socket event."; + default: + return "UNKNOWN."; + } +} + +#endif /* (SYS_LOG_LEVEL > SYS_LOG_LEVEL_OFF) */ + +/** + * This function is called when the socket is to be opened. + */ +static int winc1500_get(sa_family_t family, + enum net_sock_type type, + enum net_ip_protocol ip_proto, + struct net_context **context) +{ + struct socket_data *sd; + + if (family != AF_INET) { + SYS_LOG_ERR("Only AF_INET is supported!"); + return -1; + } + + (*context)->user_data = (void *)(sint32)socket(family, type, 0); + if ((*context)->user_data < 0) { + SYS_LOG_ERR("socket error!"); + return -1; + } + + sd = &w1500_data.socket_data[(int)(*context)->user_data]; + + k_sem_init(&sd->wait_sem, 0, 1); + + sd->context = *context; + + return 0; +} + +/** + * This function is called when user wants to bind to local IP address. + */ +static int winc1500_bind(struct net_context *context, + const struct sockaddr *addr, + socklen_t addrlen) +{ + SOCKET socket = (int)context->user_data; + int ret; + + /* FIXME atmel winc1500 don't support bind on null port */ + if (net_sin(addr)->sin_port == 0) { + return 0; + } + + ret = bind((int)context->user_data, (struct sockaddr *)addr, addrlen); + if (ret) { + SYS_LOG_ERR("bind error %d %s!", + ret, socket_message_to_string(ret)); + return ret; + } + + if (k_sem_take(&w1500_data.socket_data[socket].wait_sem, + WINC1500_BIND_TIMEOUT)) { + SYS_LOG_ERR("bind error timeout expired"); + return -ETIMEDOUT; + } + + return w1500_data.socket_data[socket].ret_code; +} + +/** + * This function is called when user wants to mark the socket + * to be a listening one. + */ +static int winc1500_listen(struct net_context *context, int backlog) +{ + SOCKET socket = (int)context->user_data; + int ret; + + ret = listen((int)context->user_data, backlog); + if (ret) { + SYS_LOG_ERR("listen error %d %s!", + ret, socket_error_string(ret)); + return ret; + } + + if (k_sem_take(&w1500_data.socket_data[socket].wait_sem, + WINC1500_LISTEN_TIMEOUT)) { + return -ETIMEDOUT; + } + + return w1500_data.socket_data[socket].ret_code; +} + +/** + * This function is called when user wants to create a connection + * to a peer host. + */ +static int winc1500_connect(struct net_context *context, + const struct sockaddr *addr, + socklen_t addrlen, + net_context_connect_cb_t cb, + s32_t timeout, + void *user_data) +{ + SOCKET socket = (int)context->user_data; + int ret; + + w1500_data.socket_data[socket].connect_cb = cb; + w1500_data.socket_data[socket].connect_user_data = user_data; + w1500_data.socket_data[socket].ret_code = 0; + + ret = connect(socket, (struct sockaddr *)addr, addrlen); + if (ret) { + SYS_LOG_ERR("connect error %d %s!", + ret, socket_error_string(ret)); + return ret; + } + + if (timeout != 0 && + k_sem_take(&w1500_data.socket_data[socket].wait_sem, timeout)) { + return -ETIMEDOUT; + } + + return w1500_data.socket_data[socket].ret_code; +} + +/** + * This function is called when user wants to accept a connection + * being established. + */ +static int winc1500_accept(struct net_context *context, + net_tcp_accept_cb_t cb, + s32_t timeout, + void *user_data) +{ + SOCKET socket = (int)context->user_data; + int ret; + + w1500_data.socket_data[socket].accept_cb = cb; + + ret = accept(socket, NULL, 0); + if (ret) { + SYS_LOG_ERR("accept error %d %s!", + ret, socket_error_string(ret)); + return ret; + } + + if (timeout) { + if (k_sem_take(&w1500_data.socket_data[socket].wait_sem, + timeout)) { + return -ETIMEDOUT; + } + } else { + k_sem_take(&w1500_data.socket_data[socket].wait_sem, + K_FOREVER); + } + + return w1500_data.socket_data[socket].ret_code; +} + +/** + * This function is called when user wants to send data to peer host. + */ +static int winc1500_send(struct net_pkt *pkt, + net_context_send_cb_t cb, + s32_t timeout, + void *token, + void *user_data) +{ + struct net_context *context = pkt->context; + SOCKET socket = (int)context->user_data; + bool first_frag; + struct net_buf *frag; + int ret; + + w1500_data.socket_data[socket].send_cb = cb; + w1500_data.socket_data[socket].send_user_data = user_data; + + first_frag = true; + + for (frag = pkt->frags; frag; frag = frag->frags) { + u8_t *data_ptr; + u16_t data_len; + + if (first_frag) { + data_ptr = net_pkt_ll(pkt); + data_len = net_pkt_ll_reserve(pkt) + frag->len; + first_frag = false; + } else { + data_ptr = frag->data; + data_len = frag->len; + + } + + ret = send(socket, data_ptr, data_len, 0); + if (ret) { + SYS_LOG_ERR("send error %d %s!", + ret, socket_error_string(ret)); + return ret; + } + } + + net_pkt_unref(pkt); + + return 0; +} + +/** + * This function is called when user wants to send data to peer host. + */ +static int winc1500_sendto(struct net_pkt *pkt, + const struct sockaddr *dst_addr, + socklen_t addrlen, + net_context_send_cb_t cb, + s32_t timeout, + void *token, + void *user_data) +{ + struct net_context *context = pkt->context; + SOCKET socket = (int)context->user_data; + bool first_frag; + struct net_buf *frag; + int ret; + + w1500_data.socket_data[socket].send_cb = cb; + w1500_data.socket_data[socket].send_user_data = user_data; + + first_frag = true; + + for (frag = pkt->frags; frag; frag = frag->frags) { + u8_t *data_ptr; + u16_t data_len; + + if (first_frag) { + data_ptr = net_pkt_ll(pkt); + data_len = net_pkt_ll_reserve(pkt) + frag->len; + first_frag = false; + } else { + data_ptr = frag->data; + data_len = frag->len; + } + + ret = sendto(socket, data_ptr, data_len, 0, + (struct sockaddr *)dst_addr, addrlen); + if (ret) { + SYS_LOG_ERR("send error %d %s!", + ret, socket_error_string(ret)); + return ret; + } + } + + net_pkt_unref(pkt); + + return 0; +} + +/** + */ +static int prepare_pkt(struct socket_data *sock_data) +{ + /* Get the frame from the buffer */ + sock_data->rx_pkt = net_pkt_get_reserve_rx(0, K_NO_WAIT); + if (!sock_data->rx_pkt) { + SYS_LOG_ERR("Could not allocate rx packet"); + return -1; + } + + /* Reserve a data frag to receive the frame */ + sock_data->pkt_buf = net_pkt_get_frag(sock_data->rx_pkt, K_NO_WAIT); + if (!sock_data->pkt_buf) { + SYS_LOG_ERR("Could not allocate data frag"); + net_pkt_unref(sock_data->rx_pkt); + return -1; + } + + net_pkt_frag_insert(sock_data->rx_pkt, sock_data->pkt_buf); + + return 0; +} + +/** + * This function is called when user wants to receive data from peer + * host. + */ +static int winc1500_recv(struct net_context *context, + net_context_recv_cb_t cb, + s32_t timeout, + void *user_data) +{ + SOCKET socket = (int) context->user_data; + int ret; + + ret = prepare_pkt(&w1500_data.socket_data[socket]); + if (ret) { + SYS_LOG_ERR("Could not reserve packet buffer"); + return -ENOMEM; + } + + w1500_data.socket_data[socket].recv_cb = cb; + w1500_data.socket_data[socket].recv_user_data = user_data; + + ret = recv(socket, w1500_data.socket_data[socket].pkt_buf->data, + CONFIG_WINC1500_MAX_PACKET_SIZE, timeout); + if (ret) { + SYS_LOG_ERR("recv error %d %s!", + ret, socket_error_string(ret)); + return ret; + } + + return 0; +} + +/** + * This function is called when user wants to close the socket. + */ +static int winc1500_put(struct net_context *context) +{ + return 0; +} + +static struct net_offload winc1500_offload = { + .get = winc1500_get, + .bind = winc1500_bind, + .listen = winc1500_listen, + .connect = winc1500_connect, + .accept = winc1500_accept, + .send = winc1500_send, + .sendto = winc1500_sendto, + .recv = winc1500_recv, + .put = winc1500_put, +}; + +static void winc1500_wifi_cb(u8_t message_type, void *pvMsg) +{ + SYS_LOG_INF("Msg Type %d %s", + message_type, wifi_cb_msg_2_str(message_type)); + + switch (message_type) { + case M2M_WIFI_RESP_CON_STATE_CHANGED: + { + tstrM2mWifiStateChanged *pstrWifiState = + (tstrM2mWifiStateChanged *)pvMsg; + + switch (pstrWifiState->u8CurrState) { + case M2M_WIFI_DISCONNECTED: + /* TODO status disconnected */ + break; + case M2M_WIFI_CONNECTED: + /* TODO status connected */ + break; + case M2M_WIFI_UNDEF: + /* TODO status undefined*/ + break; + } + } + + break; + + case M2M_WIFI_REQ_DHCP_CONF: + { + u8_t *pu8IPAddress = (u8_t *)pvMsg; + struct in_addr addr; + u8_t i; + + /* Connected and got IP address*/ + SYS_LOG_INF("Wi-Fi connected, IP is %u.%u.%u.%u", + pu8IPAddress[0], pu8IPAddress[1], + pu8IPAddress[2], pu8IPAddress[3]); + /* TODO at this point the standby mode should be enable + * status = WiFi connected IP assigned + */ + for (i = 0; i < 4; i++) { + addr.s4_addr[i] = pu8IPAddress[i]; + } + + /* TODO fill in net mask, gateway and lease time */ + + net_if_ipv4_addr_add(w1500_data.iface, + &addr, NET_ADDR_DHCP, 0); + } + + break; + + default: + break; + } + +} + +static void winc1500_socket_cb(SOCKET sock, uint8 message, void *pvMsg) +{ + struct socket_data *sd = &w1500_data.socket_data[sock]; + + if (message != 6) { + SYS_LOG_INF(": sock %d Msg %d %s", + sock, message, socket_message_to_string(message)); + } + + sd->ret_code = 0; + + switch (message) { + case SOCKET_MSG_CONNECT: + { + tstrSocketConnectMsg *strConnMsg = + (tstrSocketConnectMsg *)pvMsg; + + SYS_LOG_ERR("CONNECT: socket %d error %d", + strConnMsg->sock, strConnMsg->s8Error); + + if (sd->connect_cb) { + sd->connect_cb(sd->context, + strConnMsg->s8Error, + sd->connect_user_data); + } + + sd->ret_code = strConnMsg->s8Error; + } + k_sem_give(&sd->wait_sem); + break; + + case SOCKET_MSG_SEND: + break; + + case SOCKET_MSG_RECV: + { + tstrSocketRecvMsg *pstrRx = (tstrSocketRecvMsg *)pvMsg; + + if ((pstrRx->pu8Buffer != NULL) && + (pstrRx->s16BufferSize > 0)) { + + net_buf_add(sd->pkt_buf, + pstrRx->s16BufferSize); + + net_pkt_set_appdata(sd->rx_pkt, + sd->pkt_buf->data); + net_pkt_set_appdatalen(sd->rx_pkt, + pstrRx->s16BufferSize); + + if (sd->recv_cb) { + sd->recv_cb(sd->context, + sd->rx_pkt, + 0, + sd->recv_user_data); + } + } else if (pstrRx->pu8Buffer == NULL) { + if (pstrRx->s16BufferSize == SOCK_ERR_CONN_ABORTED) { + net_pkt_unref(sd->rx_pkt); + return; + } + } + + if (prepare_pkt(&w1500_data.socket_data[sock])) { + SYS_LOG_ERR("Could not reserve packet buffer"); + return; + } + + recv(sock, sd->pkt_buf->data, + CONFIG_WINC1500_MAX_PACKET_SIZE, K_NO_WAIT); + } + break; + case SOCKET_MSG_BIND: + { + /* The result of the bind operation. + * Holding a value of ZERO for a successful + * bind or otherwise a negative error code + * corresponding to the type of error. + */ + tstrSocketBindMsg *bind_msg = (tstrSocketBindMsg *)pvMsg; + + if (bind_msg->status) { + SYS_LOG_ERR("BIND: error %d %s", + bind_msg->status, + socket_message_to_string(bind_msg->status)); + sd->ret_code = bind_msg->status; + } + } + k_sem_give(&sd->wait_sem); + break; + case SOCKET_MSG_LISTEN: + { + /* Holding a value of ZERO for a successful listen or + * otherwise a negative error code corresponding to + * the type of error. + */ + tstrSocketListenMsg *listen_msg = (tstrSocketListenMsg *)pvMsg; + + if (listen_msg->status) { + SYS_LOG_ERR("winc1500_socket_cb:LISTEN: error %d %s\n", + listen_msg->status, + socket_message_to_string(listen_msg->status)); + sd->ret_code = listen_msg->status; + } + } + k_sem_give(&sd->wait_sem); + break; + case SOCKET_MSG_ACCEPT: + { + /* sock + * On a successful accept operation, the return information + * is the socket ID for the accepted connection with the + * remote peer. + * Otherwise a negative error code is returned to indicate + * failure of the accept operation. + * strAddr; + * Socket address structure for the remote peer. + */ + tstrSocketAcceptMsg *accept_msg = (tstrSocketAcceptMsg *)pvMsg; + + SYS_LOG_INF("ACCEPT:" + "from %d.%d.%d.%d:%d, new socket is %d", + accept_msg->strAddr.sin_addr.s4_addr[0], + accept_msg->strAddr.sin_addr.s4_addr[1], + accept_msg->strAddr.sin_addr.s4_addr[2], + accept_msg->strAddr.sin_addr.s4_addr[3], + ntohs(accept_msg->strAddr.sin_port), + accept_msg->sock); + + if (accept_msg->sock < 0) { + SYS_LOG_ERR("ACCEPT: error %d %s", + accept_msg->sock, + socket_message_to_string(accept_msg->sock)); + sd->ret_code = accept_msg->sock; + } + + if (sd->accept_cb) { + struct socket_data *a_sd; + int ret; + + a_sd = &w1500_data.socket_data[accept_msg->sock]; + + memcpy(a_sd, sd, sizeof(struct socket_data)); + + ret = net_context_get(AF_INET, SOCK_STREAM, + IPPROTO_TCP, &a_sd->context); + if (ret < 0) { + SYS_LOG_ERR("Cannot get new network" + "context for ACCEPT"); + } else { + a_sd->context->user_data = + (void *)((int)accept_msg->sock); + + sd->accept_cb( + a_sd->context, + (struct sockaddr *)&accept_msg->strAddr, + sizeof(struct sockaddr_in), + (accept_msg->sock > 0) ? + 0 :accept_msg->sock, + sd->accept_user_data); + } + } + } + k_sem_give(&sd->wait_sem); + break; + } +} + +static void winc1500_thread(void) +{ + while (1) { + while (m2m_wifi_handle_events(NULL) != 0) { + } + + k_sleep(K_MSEC(1)); + } +} + + +static void winc1500_iface_init(struct net_if *iface) +{ + SYS_LOG_INF("eth_init:net_if_set_link_addr:" + "MAC Address %02X:%02X:%02X:%02X:%02X:%02X", + w1500_data.mac[0], w1500_data.mac[1], w1500_data.mac[2], + w1500_data.mac[3], w1500_data.mac[4], w1500_data.mac[5]); + + net_if_set_link_addr(iface, w1500_data.mac, sizeof(w1500_data.mac), + NET_LINK_ETHERNET); + + iface->if_dev->offload = &winc1500_offload; + + w1500_data.iface = iface; +} + +static const struct net_if_api winc1500_api = { + .init = winc1500_iface_init, +}; + +static int winc1500_init(struct device *dev) +{ + tstrWifiInitParam param = { + .pfAppWifiCb = winc1500_wifi_cb, + }; + tuniM2MWifiAuth creds = { + .au8PSK = CONFIG_WIFI_WINC1500_PSK, + }; + unsigned char is_valid; + int ret; + + ARG_UNUSED(dev); + + ret = m2m_wifi_init(¶m); + if (ret) { + SYS_LOG_ERR("m2m_wifi_init return error!(%d)", ret); + return -EIO; + } + + socketInit(); + registerSocketCallback(winc1500_socket_cb, NULL); + + m2m_wifi_get_otp_mac_address(w1500_data.mac, &is_valid); + SYS_LOG_INF("WINC1500 MAC Address from OTP (%d) " + "%02X:%02X:%02X:%02X:%02X:%02X", + is_valid, + w1500_data.mac[0], w1500_data.mac[1], w1500_data.mac[2], + w1500_data.mac[3], w1500_data.mac[4], w1500_data.mac[5]); + + m2m_wifi_set_power_profile(PWR_LOW1); + m2m_wifi_set_tx_power(TX_PWR_LOW); + + /* monitoring thread for winc wifi callbacks */ + k_thread_create(&winc1500_thread_data, winc1500_stack, + CONFIG_WINC1500_THREAD_STACK_SIZE, + (k_thread_entry_t)winc1500_thread, NULL, NULL, NULL, + K_PRIO_COOP(CONFIG_WINC1500_THREAD_PRIO), + 0, K_NO_WAIT); + + SYS_LOG_INF("Connecting to %s (%u) with %s", + CONFIG_WIFI_WINC1500_SSID, + CONFIG_WIFI_WINC1500_SSID_LENGTH, + CONFIG_WIFI_WINC1500_PSK); + + ret = m2m_wifi_connect(CONFIG_WIFI_WINC1500_SSID, + CONFIG_WIFI_WINC1500_SSID_LENGTH, + M2M_WIFI_SEC_WPA_PSK, &creds, + M2M_WIFI_CH_ALL); + if (ret) { + SYS_LOG_WRN("Connecting to wifi does not seem to work"); + } + + SYS_LOG_INF("WINC1500 driver Initialized"); + + return 0; +} + +NET_DEVICE_OFFLOAD_INIT(winc1500, CONFIG_WIFI_WINC1500_NAME, + winc1500_init, &w1500_data, NULL, + CONFIG_WIFI_INIT_PRIORITY, &winc1500_api, + CONFIG_WINC1500_MAX_PACKET_SIZE); diff --git a/drivers/wifi/wifi_winc1500_config.h b/drivers/wifi/wifi_winc1500_config.h new file mode 100644 index 0000000000000..2b986c4a4fdf6 --- /dev/null +++ b/drivers/wifi/wifi_winc1500_config.h @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2017 IpTronix + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef CONF_WINC_H_INCLUDED +#define CONF_WINC_H_INCLUDED + +/* + --------------------------------- + ---------- PIN settings --------- + --------------------------------- + */ +#define CONF_WINC_PIN_RESET IOPORT_CREATE_PIN(PIOA, 24) +#define CONF_WINC_PIN_CHIP_ENABLE IOPORT_CREATE_PIN(PIOA, 6) +#define CONF_WINC_PIN_WAKE IOPORT_CREATE_PIN(PIOA, 25) + +/* + --------------------------------- + ---------- SPI settings --------- + --------------------------------- + */ +#define CONF_WINC_USE_SPI (1) + +/** SPI pin and instance settings. */ +#define CONF_WINC_SPI SPI +#define CONF_WINC_SPI_ID ID_SPI +#define CONF_WINC_SPI_MISO_GPIO SPI_MISO_GPIO +#define CONF_WINC_SPI_MISO_FLAGS SPI_MISO_FLAGS +#define CONF_WINC_SPI_MOSI_GPIO SPI_MOSI_GPIO +#define CONF_WINC_SPI_MOSI_FLAGS SPI_MOSI_FLAGS +#define CONF_WINC_SPI_CLK_GPIO SPI_SPCK_GPIO +#define CONF_WINC_SPI_CLK_FLAGS SPI_SPCK_FLAGS +#define CONF_WINC_SPI_CS_GPIO SPI_NPCS0_GPIO +#define CONF_WINC_SPI_CS_FLAGS PIO_OUTPUT_1 +#define CONF_WINC_SPI_NPCS (0) + +/** SPI delay before SPCK and between consecutive transfer. */ +#define CONF_WINC_SPI_DLYBS (0) +#define CONF_WINC_SPI_DLYBCT (0) + +/** SPI interrupt pin. */ +#define CONF_WINC_SPI_INT_PIN IOPORT_CREATE_PIN(PIOA, 1) +#define CONF_WINC_SPI_INT_PIO PIOA +#define CONF_WINC_SPI_INT_PIO_ID ID_PIOA +#define CONF_WINC_SPI_INT_MASK (1 << 1) +#define CONF_WINC_SPI_INT_PRIORITY (0) + +/** Clock polarity & phase. */ +#define CONF_WINC_SPI_POL (0) +#define CONF_WINC_SPI_PHA (1) + +/** SPI clock. */ +#define CONF_WINC_SPI_CLOCK (48000000) + +/* + --------------------------------- + --------- Debug Options --------- + --------------------------------- + */ +#include +#define CONF_WINC_DEBUG (0) +#define CONF_WINC_PRINTF printf + +#endif /* CONF_WINC_H_INCLUDED */ diff --git a/drivers/wifi/wifi_winc1500_nm_bsp.c b/drivers/wifi/wifi_winc1500_nm_bsp.c new file mode 100644 index 0000000000000..02259b6b5e1ec --- /dev/null +++ b/drivers/wifi/wifi_winc1500_nm_bsp.c @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2017 IpTronix + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "wifi_winc1500_nm_bsp_internal.h" + +#include +#include + +#include "wifi_winc1500_config.h" + +struct winc1500_device winc1500; + +void (*isr_function)(void); + +static inline void chip_isr(struct device *port, + struct gpio_callback *cb, + uint32_t pins) +{ + if (isr_function) { + isr_function(); + } +} + +s8_t nm_bsp_init(void) +{ + isr_function = NULL; + + /* Initialize chip IOs. */ + winc1500.gpios = winc1500_configure_gpios(); + + winc1500.spi_dev = device_get_binding(CONFIG_WINC1500_SPI_DRV_NAME); + if (!winc1500.spi_dev) { + return -1; + } + + /* Perform chip reset. */ + nm_bsp_reset(); + + return 0; +} + +s8_t nm_bsp_deinit(void) +{ + /* TODO */ + return 0; +} + +void nm_bsp_reset(void) +{ + gpio_pin_write(winc1500.gpios[WINC1500_GPIO_IDX_CHIP_EN], + CONFIG_WINC1500_GPIO_CHIP_EN, 0); + gpio_pin_write(winc1500.gpios[WINC1500_GPIO_IDX_RESET_N], + CONFIG_WINC1500_GPIO_RESET_N, 0); + nm_bsp_sleep(100); + + gpio_pin_write(winc1500.gpios[WINC1500_GPIO_IDX_CHIP_EN], + CONFIG_WINC1500_GPIO_CHIP_EN, 1); + nm_bsp_sleep(10); + + gpio_pin_write(winc1500.gpios[WINC1500_GPIO_IDX_RESET_N], + CONFIG_WINC1500_GPIO_RESET_N, 1); + nm_bsp_sleep(10); +} + +void nm_bsp_sleep(uint32 u32TimeMsec) +{ + k_busy_wait(u32TimeMsec * MSEC_PER_SEC); +} + +void nm_bsp_register_isr(void (*isr_fun)(void)) +{ + isr_function = isr_fun; + + gpio_init_callback(&winc1500.gpio_cb, + chip_isr, + BIT(CONFIG_WINC1500_GPIO_IRQN)); + + gpio_add_callback(winc1500.gpios[WINC1500_GPIO_IDX_IRQN], + &winc1500.gpio_cb); +} + +void nm_bsp_interrupt_ctrl(u8_t enable) +{ + if (enable) { + gpio_pin_enable_callback( + winc1500.gpios[WINC1500_GPIO_IDX_IRQN], + CONFIG_WINC1500_GPIO_IRQN); + } else { + gpio_pin_disable_callback( + winc1500.gpios[WINC1500_GPIO_IDX_IRQN], + CONFIG_WINC1500_GPIO_IRQN); + } +} diff --git a/drivers/wifi/wifi_winc1500_nm_bsp_internal.h b/drivers/wifi/wifi_winc1500_nm_bsp_internal.h new file mode 100644 index 0000000000000..5588436c082e6 --- /dev/null +++ b/drivers/wifi/wifi_winc1500_nm_bsp_internal.h @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2017 IpTronix + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __WIFI_WINC1500_NM_BSP_INTERNAL_H__ +#define __WIFI_WINC1500_NM_BSP_INTERNAL_H__ + +#include +#include + +#include "wifi_winc1500_config.h" +#include + +extern tstrNmBusCapabilities egstrNmBusCapabilities; + +#define NM_EDGE_INTERRUPT (1) + +#define NM_DEBUG CONF_WINC_DEBUG +#define NM_BSP_PRINTF CONF_WINC_PRINTF + +struct winc1500_device { + struct device **gpios; + struct gpio_callback gpio_cb; + + struct device *spi_dev; + int spi_slave; +}; + +extern struct winc1500_device winc1500; + +#endif /* __WIFI_WINC1500_NM_BSP_INTERNAL_H__ */ diff --git a/drivers/wifi/wifi_winc1500_nm_bus_wrapper.c b/drivers/wifi/wifi_winc1500_nm_bus_wrapper.c new file mode 100644 index 0000000000000..84bd4cdd0d566 --- /dev/null +++ b/drivers/wifi/wifi_winc1500_nm_bus_wrapper.c @@ -0,0 +1,175 @@ +/** + * Copyright (c) 2017 IpTronix + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define SYS_LOG_LEVEL CONFIG_SYS_LOG_WIFI_LEVEL +#define SYS_LOG_DOMAIN "dev/winc1500" +#include + +#include +#include + +#include +#include +#include + +#include "wifi_winc1500_nm_bsp_internal.h" + +#include +#include +#include + +#include "wifi_winc1500_config.h" + +#define NM_BUS_MAX_TRX_SZ 256 + +tstrNmBusCapabilities egstrNmBusCapabilities = { + NM_BUS_MAX_TRX_SZ +}; + +#ifdef CONF_WINC_USE_I2C + +#define SLAVE_ADDRESS 0x60 + +/** Number of times to try to send packet if failed. */ +#define I2C_TIMEOUT 100 + +static s8_t nm_i2c_write(u8_t *b, u16_t sz) +{ + /* Not implemented */ +} + +static s8_t nm_i2c_read(u8_t *rb, u16_t sz) +{ + /* Not implemented */ +} + +static s8_t nm_i2c_write_special(u8_t *wb1, u16_t sz1, + u8_t *wb2, u16_t sz2) +{ + /* Not implemented */ +} +#endif + +#ifdef CONF_WINC_USE_SPI + +static s8_t spi_rw(u8_t *mosi, u8_t *miso, u16_t size) +{ + int ret; + + spi_slave_select(winc1500.spi_dev, winc1500.spi_slave); + + ret = spi_transceive(winc1500.spi_dev, + mosi, size, + miso, miso ? size : 0); + if (ret) { + SYS_LOG_ERR("spi_transceive fail %d", ret); + return M2M_ERR_BUS_FAIL; + } + + return M2M_SUCCESS; +} + +#endif + +s8_t nm_bus_init(void *pvinit) +{ + s8_t result = 0; + +#ifdef CONF_WINC_USE_I2C + /* Not implemented */ +#elif defined CONF_WINC_USE_SPI + struct spi_config spi_config; + int ret; + + /* configure GPIOs */ + winc1500.gpios = winc1500_configure_gpios(); + + /* setup SPI device */ + winc1500.spi_dev = device_get_binding( + CONFIG_WIFI_WINC1500_SPI_DRV_NAME); + if (!winc1500.spi_dev) { + SYS_LOG_ERR("spi device binding"); + return -1; + } + + spi_config.config = SPI_WORD(8) | SPI_TRANSFER_MSB; + spi_config.max_sys_freq = CONFIG_WIFI_WINC1500_SPI_FREQ; + + ret = spi_configure(winc1500.spi_dev, &spi_config); + if (ret) { + SYS_LOG_ERR("spi_configure fail %d", ret); + return -1; + } + + winc1500.spi_slave = CONFIG_WIFI_WINC1500_SPI_SLAVE; + SYS_LOG_INF("spi_configure OK"); + + winc1500_configure_intgpios(); + + nm_bsp_reset(); + nm_bsp_sleep(1); + + nm_bsp_interrupt_ctrl(1); + + SYS_LOG_INF("NOTICE:DONE"); +#endif + return result; +} + +s8_t nm_bus_ioctl(u8_t cmd, void *parameter) +{ + sint8 ret = 0; + + switch (cmd) { +#ifdef CONF_WINC_USE_I2C + case NM_BUS_IOCTL_R: { + struct nm_i2c_default *param = + (struct nm_i2c_default *)parameter; + + ret = nm_i2c_read(param->buffer, param->size); + } + break; + case NM_BUS_IOCTL_W: { + struct nm_i2c_default *param = + (struct nm_i2c_default *)parameter; + + ret = nm_i2c_write(param->buffer, param->size); + } + break; + case NM_BUS_IOCTL_W_SPECIAL: { + struct nm_i2c_special *param = + (struct nm_i2c_special *)parameter; + + ret = nm_i2c_write_special(param->buffer1, param->size1, + param->buffer2, param->size2); + } + break; +#elif defined CONF_WINC_USE_SPI + case NM_BUS_IOCTL_RW: { + tstrNmSpiRw *param = (tstrNmSpiRw *)parameter; + + ret = spi_rw(param->pu8InBuf, param->pu8OutBuf, param->u16Sz); + } + break; +#endif + default: + ret = -1; + M2M_ERR("ERROR:invalid ioclt cmd\n"); + break; + } + + return ret; +} + +s8_t nm_bus_deinit(void) +{ + return M2M_SUCCESS; +} + +s8_t nm_bus_reinit(void *config) +{ + return 0; +} diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/bsp/include/nm_bsp_internal.h b/ext/hal/atmel/asf/common/components/wifi/winc1500/bsp/include/nm_bsp_internal.h index 2608731069734..e794484ad90bb 100644 --- a/ext/hal/atmel/asf/common/components/wifi/winc1500/bsp/include/nm_bsp_internal.h +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/bsp/include/nm_bsp_internal.h @@ -7,6 +7,8 @@ #ifndef _NM_BSP_INTERNAL_H_ #define _NM_BSP_INTERNAL_H_ -/* dummy nm_bsp_internal.h to make nm_debug.c happy */ +#if defined(CONFIG_WIFI_WINC1500) +#include +#endif /* CONFIG_WIFI_WINC1500 */ #endif //_NM_BSP_INTERNAL_H_ From d2a72050a5520b33854fc75c8272e0165a96bb61 Mon Sep 17 00:00:00 2001 From: Tomasz Bursztyka Date: Thu, 2 Nov 2017 12:07:25 +0100 Subject: [PATCH 03/13] drivers/wifi: Generalize GPIO configuration for the WINC1500 driver Previous way was cumbersome (based on an old way for cc2520 actually), so moving towards the more recent and proper way. This will enable anybody to actually provide gpio configuration for a winc1500 out of any board specific location. Signed-off-by: Tomasz Bursztyka --- drivers/wifi/Kconfig.winc1500 | 2 -- drivers/wifi/wifi_winc1500_nm_bsp.c | 28 +++++++++---------- drivers/wifi/wifi_winc1500_nm_bsp_internal.h | 10 ++++--- drivers/wifi/wifi_winc1500_nm_bus_wrapper.c | 2 -- .../components/wifi/winc1500/CMakeLists.txt | 5 +++- include/drivers/wifi/winc1500.h | 23 +++++++++++++++ 6 files changed, 47 insertions(+), 23 deletions(-) create mode 100644 include/drivers/wifi/winc1500.h diff --git a/drivers/wifi/Kconfig.winc1500 b/drivers/wifi/Kconfig.winc1500 index 488ca78a8796d..dbc385c5b42f7 100644 --- a/drivers/wifi/Kconfig.winc1500 +++ b/drivers/wifi/Kconfig.winc1500 @@ -37,8 +37,6 @@ config WIFI_WINC1500_SPI_FREQ help SPI frequency to use with WINC1500 -# TODO GPIO - config WIFI_WINC1500_SSID string "SSID the chip shall try to connect to" default "" diff --git a/drivers/wifi/wifi_winc1500_nm_bsp.c b/drivers/wifi/wifi_winc1500_nm_bsp.c index 02259b6b5e1ec..bffa9700a323c 100644 --- a/drivers/wifi/wifi_winc1500_nm_bsp.c +++ b/drivers/wifi/wifi_winc1500_nm_bsp.c @@ -52,18 +52,18 @@ s8_t nm_bsp_deinit(void) void nm_bsp_reset(void) { - gpio_pin_write(winc1500.gpios[WINC1500_GPIO_IDX_CHIP_EN], - CONFIG_WINC1500_GPIO_CHIP_EN, 0); - gpio_pin_write(winc1500.gpios[WINC1500_GPIO_IDX_RESET_N], - CONFIG_WINC1500_GPIO_RESET_N, 0); + gpio_pin_write(winc1500.gpios[WINC1500_GPIO_IDX_CHIP_EN].dev, + winc1500.gpios[WINC1500_GPIO_IDX_CHIP_EN].pin, 0); + gpio_pin_write(winc1500.gpios[WINC1500_GPIO_IDX_RESET_N].dev, + winc1500.gpios[WINC1500_GPIO_IDX_RESET_N].pin, 0); nm_bsp_sleep(100); - gpio_pin_write(winc1500.gpios[WINC1500_GPIO_IDX_CHIP_EN], - CONFIG_WINC1500_GPIO_CHIP_EN, 1); + gpio_pin_write(winc1500.gpios[WINC1500_GPIO_IDX_CHIP_EN].dev, + winc1500.gpios[WINC1500_GPIO_IDX_CHIP_EN].pin, 1); nm_bsp_sleep(10); - gpio_pin_write(winc1500.gpios[WINC1500_GPIO_IDX_RESET_N], - CONFIG_WINC1500_GPIO_RESET_N, 1); + gpio_pin_write(winc1500.gpios[WINC1500_GPIO_IDX_RESET_N].dev, + winc1500.gpios[WINC1500_GPIO_IDX_RESET_N].pin, 1); nm_bsp_sleep(10); } @@ -78,9 +78,9 @@ void nm_bsp_register_isr(void (*isr_fun)(void)) gpio_init_callback(&winc1500.gpio_cb, chip_isr, - BIT(CONFIG_WINC1500_GPIO_IRQN)); + BIT(winc1500.gpios[WINC1500_GPIO_IDX_IRQN].pin)); - gpio_add_callback(winc1500.gpios[WINC1500_GPIO_IDX_IRQN], + gpio_add_callback(winc1500.gpios[WINC1500_GPIO_IDX_IRQN].dev, &winc1500.gpio_cb); } @@ -88,11 +88,11 @@ void nm_bsp_interrupt_ctrl(u8_t enable) { if (enable) { gpio_pin_enable_callback( - winc1500.gpios[WINC1500_GPIO_IDX_IRQN], - CONFIG_WINC1500_GPIO_IRQN); + winc1500.gpios[WINC1500_GPIO_IDX_IRQN].dev, + winc1500.gpios[WINC1500_GPIO_IDX_IRQN].pin); } else { gpio_pin_disable_callback( - winc1500.gpios[WINC1500_GPIO_IDX_IRQN], - CONFIG_WINC1500_GPIO_IRQN); + winc1500.gpios[WINC1500_GPIO_IDX_IRQN].dev, + winc1500.gpios[WINC1500_GPIO_IDX_IRQN].pin); } } diff --git a/drivers/wifi/wifi_winc1500_nm_bsp_internal.h b/drivers/wifi/wifi_winc1500_nm_bsp_internal.h index 5588436c082e6..bca0b2330482d 100644 --- a/drivers/wifi/wifi_winc1500_nm_bsp_internal.h +++ b/drivers/wifi/wifi_winc1500_nm_bsp_internal.h @@ -10,6 +10,8 @@ #include #include +#include + #include "wifi_winc1500_config.h" #include @@ -21,11 +23,11 @@ extern tstrNmBusCapabilities egstrNmBusCapabilities; #define NM_BSP_PRINTF CONF_WINC_PRINTF struct winc1500_device { - struct device **gpios; - struct gpio_callback gpio_cb; + struct winc1500_gpio_configuration *gpios; + struct gpio_callback gpio_cb; - struct device *spi_dev; - int spi_slave; + struct device *spi_dev; + int spi_slave; }; extern struct winc1500_device winc1500; diff --git a/drivers/wifi/wifi_winc1500_nm_bus_wrapper.c b/drivers/wifi/wifi_winc1500_nm_bus_wrapper.c index 84bd4cdd0d566..001f752aa256c 100644 --- a/drivers/wifi/wifi_winc1500_nm_bus_wrapper.c +++ b/drivers/wifi/wifi_winc1500_nm_bus_wrapper.c @@ -107,8 +107,6 @@ s8_t nm_bus_init(void *pvinit) winc1500.spi_slave = CONFIG_WIFI_WINC1500_SPI_SLAVE; SYS_LOG_INF("spi_configure OK"); - winc1500_configure_intgpios(); - nm_bsp_reset(); nm_bsp_sleep(1); diff --git a/ext/hal/atmel/asf/common/components/wifi/winc1500/CMakeLists.txt b/ext/hal/atmel/asf/common/components/wifi/winc1500/CMakeLists.txt index 90116c63250f2..867a608a6c721 100644 --- a/ext/hal/atmel/asf/common/components/wifi/winc1500/CMakeLists.txt +++ b/ext/hal/atmel/asf/common/components/wifi/winc1500/CMakeLists.txt @@ -1,4 +1,7 @@ -zephyr_include_directories(./) +zephyr_include_directories( + ./ + $ENV{ZEPHYR_BASE}/include/drivers + ) zephyr_sources( driver/source/m2m_ate_mode.c diff --git a/include/drivers/wifi/winc1500.h b/include/drivers/wifi/winc1500.h new file mode 100644 index 0000000000000..ea824fabb5923 --- /dev/null +++ b/include/drivers/wifi/winc1500.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +enum winc1500_gpio_index { + WINC1500_GPIO_IDX_CHIP_EN = 0, + WINC1500_GPIO_IDX_WAKE, + WINC1500_GPIO_IDX_IRQN, + WINC1500_GPIO_IDX_RESET_N, + + WINC1500_GPIO_IDX_MAX +}; + +struct winc1500_gpio_configuration { + struct device *dev; + u32_t pin; +}; + +struct winc1500_gpio_configuration *winc1500_configure_gpios(void); From 42ce750453bf8b4066005e80841346c8b1b6812a Mon Sep 17 00:00:00 2001 From: Tomasz Bursztyka Date: Thu, 2 Nov 2017 14:31:38 +0100 Subject: [PATCH 04/13] drivers/wifi: Move configure macros to Kconfig There is no point having undocumented and local config options when Kconfig can be used to expose these relevantly. Signed-off-by: Tomasz Bursztyka --- drivers/wifi/Kconfig.winc1500 | 39 +++++++++++++++++++++++++++++++++- drivers/wifi/wifi_winc1500.c | 40 +++++++++++------------------------ 2 files changed, 50 insertions(+), 29 deletions(-) diff --git a/drivers/wifi/Kconfig.winc1500 b/drivers/wifi/Kconfig.winc1500 index dbc385c5b42f7..56a6ac16974a1 100644 --- a/drivers/wifi/Kconfig.winc1500 +++ b/drivers/wifi/Kconfig.winc1500 @@ -31,12 +31,49 @@ config WIFI_WINC1500_SPI_SLAVE Specify the slave select pin of the SPI to which WINC1500 is connected. -config WIFI_WINC1500_SPI_FREQ +config WIFI_WIFI_WINC1500_SPI_FREQ int "SPI frequency to use with WINC1500" default 4 help SPI frequency to use with WINC1500 +config WIFI_WINC1500_THREAD_STACK_SIZE + int "HAL callback handler thread stack size" + default 2048 + help + This option sets the size of the stack used by the thread handling + WINC1500 HAL callbacks. Do not touch it unless you know what you are + doing. + +config WIFI_WINC1500_THREAD_PRIO + int "HAL callback handler thread priority" + default 2 + help + This option sets the priority of the thread handling WINC1500 HAL + callbacks. Do not touch it unless you know what you are doing. + +config WIFI_WINC1500_BUF_CTR + int "Number of buffer per-buffer pool" + default 1 + help + Set the number of buffer the driver will have access to in each of + its buffer pools. + +config WIFI_WINC1500_MAX_PACKET_SIZE + int "Maximum size of a packet, in bytes" + default 1500 + help + Set the maximum size of a network packet going through the chip. + This sets the size of each buffer, in each buffe pools. + Do not modify it unless you know what you are doing. + +config WIFI_WINC1500_OFFLOAD_MAX_SOCKETS + int "Maximum number of sockets that can be managed" + default 2 + help + Set the number of sockets that can be managed through the driver + and the chip. + config WIFI_WINC1500_SSID string "SSID the chip shall try to connect to" default "" diff --git a/drivers/wifi/wifi_winc1500.c b/drivers/wifi/wifi_winc1500.c index bb1a935698153..9616c25ee6225 100644 --- a/drivers/wifi/wifi_winc1500.c +++ b/drivers/wifi/wifi_winc1500.c @@ -106,32 +106,15 @@ typedef struct { #include #include -#ifndef CONFIG_WINC1500_THREAD_STACK_SIZE -#define CONFIG_WINC1500_THREAD_STACK_SIZE 5000 -#endif -#ifndef CONFIG_WINC1500_THREAD_PRIO -#define CONFIG_WINC1500_THREAD_PRIO 2 -#endif - -#ifndef CONFIG_WINC1500_BUF_CTR -#define CONFIG_WINC1500_BUF_CTR 1 -#endif -#ifndef CONFIG_WINC1500_MAX_PACKET_SIZE -#define CONFIG_WINC1500_MAX_PACKET_SIZE 1500 -#endif -#ifndef CONFIG_OFFLOAD_MAX_SOCKETS -#define CONFIG_OFFLOAD_MAX_SOCKETS 2 -#endif - #define WINC1500_BIND_TIMEOUT 500 #define WINC1500_LISTEN_TIMEOUT 500 -NET_BUF_POOL_DEFINE(winc1500_tx_pool, CONFIG_WINC1500_BUF_CTR, - CONFIG_WINC1500_MAX_PACKET_SIZE, 0, NULL); -NET_BUF_POOL_DEFINE(winc1500_rx_pool, CONFIG_WINC1500_BUF_CTR, - CONFIG_WINC1500_MAX_PACKET_SIZE, 0, NULL); +NET_BUF_POOL_DEFINE(winc1500_tx_pool, CONFIG_WIFI_WINC1500_BUF_CTR, + CONFIG_WIFI_WINC1500_MAX_PACKET_SIZE, 0, NULL); +NET_BUF_POOL_DEFINE(winc1500_rx_pool, CONFIG_WIFI_WINC1500_BUF_CTR, + CONFIG_WIFI_WINC1500_MAX_PACKET_SIZE, 0, NULL); -K_THREAD_STACK_MEMBER(winc1500_stack, CONFIG_WINC1500_THREAD_STACK_SIZE); +K_THREAD_STACK_MEMBER(winc1500_stack, CONFIG_WIFI_WINC1500_THREAD_STACK_SIZE); struct k_thread winc1500_thread_data; struct socket_data { @@ -151,7 +134,8 @@ struct socket_data { }; struct winc1500_data { - struct socket_data socket_data[CONFIG_OFFLOAD_MAX_SOCKETS]; + struct socket_data socket_data[ + CONFIG_WIFI_WINC1500_OFFLOAD_MAX_SOCKETS]; struct net_if *iface; unsigned char mac[6]; }; @@ -577,7 +561,7 @@ static int winc1500_recv(struct net_context *context, w1500_data.socket_data[socket].recv_user_data = user_data; ret = recv(socket, w1500_data.socket_data[socket].pkt_buf->data, - CONFIG_WINC1500_MAX_PACKET_SIZE, timeout); + CONFIG_WIFI_WINC1500_MAX_PACKET_SIZE, timeout); if (ret) { SYS_LOG_ERR("recv error %d %s!", ret, socket_error_string(ret)); @@ -732,7 +716,7 @@ static void winc1500_socket_cb(SOCKET sock, uint8 message, void *pvMsg) } recv(sock, sd->pkt_buf->data, - CONFIG_WINC1500_MAX_PACKET_SIZE, K_NO_WAIT); + CONFIG_WIFI_WINC1500_MAX_PACKET_SIZE, K_NO_WAIT); } break; case SOCKET_MSG_BIND: @@ -895,9 +879,9 @@ static int winc1500_init(struct device *dev) /* monitoring thread for winc wifi callbacks */ k_thread_create(&winc1500_thread_data, winc1500_stack, - CONFIG_WINC1500_THREAD_STACK_SIZE, + CONFIG_WIFI_WINC1500_THREAD_STACK_SIZE, (k_thread_entry_t)winc1500_thread, NULL, NULL, NULL, - K_PRIO_COOP(CONFIG_WINC1500_THREAD_PRIO), + K_PRIO_COOP(CONFIG_WIFI_WINC1500_THREAD_PRIO), 0, K_NO_WAIT); SYS_LOG_INF("Connecting to %s (%u) with %s", @@ -921,4 +905,4 @@ static int winc1500_init(struct device *dev) NET_DEVICE_OFFLOAD_INIT(winc1500, CONFIG_WIFI_WINC1500_NAME, winc1500_init, &w1500_data, NULL, CONFIG_WIFI_INIT_PRIORITY, &winc1500_api, - CONFIG_WINC1500_MAX_PACKET_SIZE); + CONFIG_WIFI_WINC1500_MAX_PACKET_SIZE); From 1488efa19cd4224000aa0a43042938d6911f6073 Mon Sep 17 00:00:00 2001 From: Tomasz Bursztyka Date: Thu, 2 Nov 2017 17:28:19 +0100 Subject: [PATCH 05/13] drivers/wifi: Let's go away from SPI legacy API in WINC1500 As legacy API is meant to be removed. Signed-off-by: Tomasz Bursztyka --- drivers/wifi/Kconfig.winc1500 | 27 +++++++- drivers/wifi/wifi_winc1500_nm_bsp.c | 5 -- drivers/wifi/wifi_winc1500_nm_bsp_internal.h | 6 +- drivers/wifi/wifi_winc1500_nm_bus_wrapper.c | 70 ++++++++++++-------- 4 files changed, 72 insertions(+), 36 deletions(-) diff --git a/drivers/wifi/Kconfig.winc1500 b/drivers/wifi/Kconfig.winc1500 index 56a6ac16974a1..1ec2a9aba498b 100644 --- a/drivers/wifi/Kconfig.winc1500 +++ b/drivers/wifi/Kconfig.winc1500 @@ -31,12 +31,35 @@ config WIFI_WINC1500_SPI_SLAVE Specify the slave select pin of the SPI to which WINC1500 is connected. -config WIFI_WIFI_WINC1500_SPI_FREQ +config WIFI_WINC1500_SPI_FREQ int "SPI frequency to use with WINC1500" - default 4 + default 8000000 help SPI frequency to use with WINC1500 +config WIFI_WINC1500_GPIO_SPI_CS + bool "Manage SPI CS through a GPIO pin" + default n + help + This option is useful if one needs to manage SPI CS through a GPIO + pin to by-pass the SPI controller's CS logic. + +config WIFI_WINC1500_GPIO_SPI_CS_DRV_NAME + string "GPIO driver's name to use to drive SPI CS through" + default "" + depends on WIFI_WINC1500_GPIO_SPI_CS + help + This option is mandatory to set which GPIO controller to use in + order to actually emulate the SPI CS. + +config WIFI_WINC1500_GPIO_SPI_CS_PIN + int "GPIO PIN to use to drive SPI CS through" + default 0 + depends on WIFI_WINC1500_GPIO_SPI_CS + help + This option is mandatory to set which GPIO pin to use in order + to actually emulate the SPI CS. + config WIFI_WINC1500_THREAD_STACK_SIZE int "HAL callback handler thread stack size" default 2048 diff --git a/drivers/wifi/wifi_winc1500_nm_bsp.c b/drivers/wifi/wifi_winc1500_nm_bsp.c index bffa9700a323c..84a60ddf67d02 100644 --- a/drivers/wifi/wifi_winc1500_nm_bsp.c +++ b/drivers/wifi/wifi_winc1500_nm_bsp.c @@ -33,11 +33,6 @@ s8_t nm_bsp_init(void) /* Initialize chip IOs. */ winc1500.gpios = winc1500_configure_gpios(); - winc1500.spi_dev = device_get_binding(CONFIG_WINC1500_SPI_DRV_NAME); - if (!winc1500.spi_dev) { - return -1; - } - /* Perform chip reset. */ nm_bsp_reset(); diff --git a/drivers/wifi/wifi_winc1500_nm_bsp_internal.h b/drivers/wifi/wifi_winc1500_nm_bsp_internal.h index bca0b2330482d..9fc4e25b84db3 100644 --- a/drivers/wifi/wifi_winc1500_nm_bsp_internal.h +++ b/drivers/wifi/wifi_winc1500_nm_bsp_internal.h @@ -9,6 +9,7 @@ #include #include +#include #include @@ -25,9 +26,8 @@ extern tstrNmBusCapabilities egstrNmBusCapabilities; struct winc1500_device { struct winc1500_gpio_configuration *gpios; struct gpio_callback gpio_cb; - - struct device *spi_dev; - int spi_slave; + struct device *spi; + struct spi_config spi_cfg; }; extern struct winc1500_device winc1500; diff --git a/drivers/wifi/wifi_winc1500_nm_bus_wrapper.c b/drivers/wifi/wifi_winc1500_nm_bus_wrapper.c index 001f752aa256c..0baa32dd513a3 100644 --- a/drivers/wifi/wifi_winc1500_nm_bus_wrapper.c +++ b/drivers/wifi/wifi_winc1500_nm_bus_wrapper.c @@ -55,17 +55,31 @@ static s8_t nm_i2c_write_special(u8_t *wb1, u16_t sz1, #ifdef CONF_WINC_USE_SPI +#ifdef CONFIG_WIFI_WINC1500_GPIO_SPI_CS +struct spi_cs_control cs_ctrl; +#endif + static s8_t spi_rw(u8_t *mosi, u8_t *miso, u16_t size) { - int ret; - - spi_slave_select(winc1500.spi_dev, winc1500.spi_slave); - - ret = spi_transceive(winc1500.spi_dev, - mosi, size, - miso, miso ? size : 0); - if (ret) { - SYS_LOG_ERR("spi_transceive fail %d", ret); + const struct spi_buf buf_tx = { + .buf = mosi, + .len = size + }; + const struct spi_buf_set tx = { + .buffers = &buf_tx, + .count = 1 + }; + const struct spi_buf buf_rx = { + .buf = miso, + .len = miso ? size : 0 + }; + const struct spi_buf_set rx = { + .buffers = &buf_rx, + .count = 1 + }; + + if (spi_transceive(winc1500.spi, &winc1500.spi_cfg, &tx, &rx)) { + SYS_LOG_ERR("spi_transceive fail"); return M2M_ERR_BUS_FAIL; } @@ -76,36 +90,40 @@ static s8_t spi_rw(u8_t *mosi, u8_t *miso, u16_t size) s8_t nm_bus_init(void *pvinit) { - s8_t result = 0; - #ifdef CONF_WINC_USE_I2C /* Not implemented */ #elif defined CONF_WINC_USE_SPI - struct spi_config spi_config; - int ret; - /* configure GPIOs */ winc1500.gpios = winc1500_configure_gpios(); /* setup SPI device */ - winc1500.spi_dev = device_get_binding( - CONFIG_WIFI_WINC1500_SPI_DRV_NAME); - if (!winc1500.spi_dev) { + winc1500.spi = device_get_binding(CONFIG_WIFI_WINC1500_SPI_DRV_NAME); + if (!winc1500.spi) { SYS_LOG_ERR("spi device binding"); return -1; } - spi_config.config = SPI_WORD(8) | SPI_TRANSFER_MSB; - spi_config.max_sys_freq = CONFIG_WIFI_WINC1500_SPI_FREQ; + winc1500.spi_cfg.operation = SPI_WORD_SET(8) | SPI_TRANSFER_MSB; + winc1500.spi_cfg.frequency = CONFIG_WIFI_WINC1500_SPI_FREQ; + winc1500.spi_cfg.slave = CONFIG_WIFI_WINC1500_SPI_SLAVE; - ret = spi_configure(winc1500.spi_dev, &spi_config); - if (ret) { - SYS_LOG_ERR("spi_configure fail %d", ret); - return -1; +#ifdef CONFIG_WIFI_WINC1500_GPIO_SPI_CS + cs_ctrl.gpio_dev = device_get_binding( + CONFIG_WIFI_WINC1500_GPIO_SPI_CS_DRV_NAME); + if (!cs_ctrl.gpio_dev) { + SYS_LOG_ERR("Unable to get GPIO SPI CS device"); + return -ENODEV; } - winc1500.spi_slave = CONFIG_WIFI_WINC1500_SPI_SLAVE; - SYS_LOG_INF("spi_configure OK"); + cs_ctrl.gpio_pin = CONFIG_WIFI_WINC1500_GPIO_SPI_CS_PIN; + cs_ctrl.delay = 0; + + winc1500.spi_cfg.cs = &cs_ctrl; + + SYS_LOG_DBG("SPI GPIO CS configured on %s:%u", + CONFIG_WIFI_WINC1500_GPIO_SPI_CS_DRV_NAME, + CONFIG_WIFI_WINC1500_GPIO_SPI_CS_PIN); +#endif /* CONFIG_WIFI_WINC1500_GPIO_SPI_CS */ nm_bsp_reset(); nm_bsp_sleep(1); @@ -114,7 +132,7 @@ s8_t nm_bus_init(void *pvinit) SYS_LOG_INF("NOTICE:DONE"); #endif - return result; + return 0; } s8_t nm_bus_ioctl(u8_t cmd, void *parameter) From fb7bfb326f76d866342bdf95da6fe55253859498 Mon Sep 17 00:00:00 2001 From: Tomasz Bursztyka Date: Fri, 3 Nov 2017 08:05:56 +0100 Subject: [PATCH 06/13] drivers/wifi: Remove useless gpio configuration call in winc1500 driver This call is already made in nm_bus_wrapper along with SPI. In nm_bus_wrapper however: moving the call out of #ifdefsf as it is generic call, whatever bus would be choosen. Signed-off-by: Tomasz Bursztyka --- drivers/wifi/wifi_winc1500_nm_bsp.c | 3 --- drivers/wifi/wifi_winc1500_nm_bus_wrapper.c | 6 +++--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/wifi/wifi_winc1500_nm_bsp.c b/drivers/wifi/wifi_winc1500_nm_bsp.c index 84a60ddf67d02..df5065308d862 100644 --- a/drivers/wifi/wifi_winc1500_nm_bsp.c +++ b/drivers/wifi/wifi_winc1500_nm_bsp.c @@ -30,9 +30,6 @@ s8_t nm_bsp_init(void) { isr_function = NULL; - /* Initialize chip IOs. */ - winc1500.gpios = winc1500_configure_gpios(); - /* Perform chip reset. */ nm_bsp_reset(); diff --git a/drivers/wifi/wifi_winc1500_nm_bus_wrapper.c b/drivers/wifi/wifi_winc1500_nm_bus_wrapper.c index 0baa32dd513a3..230f36d044d90 100644 --- a/drivers/wifi/wifi_winc1500_nm_bus_wrapper.c +++ b/drivers/wifi/wifi_winc1500_nm_bus_wrapper.c @@ -90,12 +90,12 @@ static s8_t spi_rw(u8_t *mosi, u8_t *miso, u16_t size) s8_t nm_bus_init(void *pvinit) { -#ifdef CONF_WINC_USE_I2C - /* Not implemented */ -#elif defined CONF_WINC_USE_SPI /* configure GPIOs */ winc1500.gpios = winc1500_configure_gpios(); +#ifdef CONF_WINC_USE_I2C + /* Not implemented */ +#elif defined CONF_WINC_USE_SPI /* setup SPI device */ winc1500.spi = device_get_binding(CONFIG_WIFI_WINC1500_SPI_DRV_NAME); if (!winc1500.spi) { From bb243e1d69f5e3834a17bb1c23cc2ac254072bf5 Mon Sep 17 00:00:00 2001 From: Tomasz Bursztyka Date: Fri, 3 Nov 2017 09:25:01 +0100 Subject: [PATCH 07/13] drivers/wifi: Split case logic into functions in winc1500 driver This cleans up the callback functions and isolate each part to a relevant handler to improve readability. Signed-off-by: Tomasz Bursztyka --- drivers/wifi/wifi_winc1500.c | 354 ++++++++++++++++++----------------- 1 file changed, 184 insertions(+), 170 deletions(-) diff --git a/drivers/wifi/wifi_winc1500.c b/drivers/wifi/wifi_winc1500.c index 9616c25ee6225..1ae0989076bb6 100644 --- a/drivers/wifi/wifi_winc1500.c +++ b/drivers/wifi/wifi_winc1500.c @@ -591,6 +591,47 @@ static struct net_offload winc1500_offload = { .put = winc1500_put, }; +static void handle_wifi_con_state_changed(void *pvMsg) +{ + tstrM2mWifiStateChanged *pstrWifiState = + (tstrM2mWifiStateChanged *)pvMsg; + + switch (pstrWifiState->u8CurrState) { + case M2M_WIFI_DISCONNECTED: + /* TODO status disconnected */ + break; + case M2M_WIFI_CONNECTED: + /* TODO status connected */ + break; + case M2M_WIFI_UNDEF: + /* TODO status undefined*/ + break; + } +} + +static void handle_wifi_dhcp_conf(void *pvMsg) +{ + u8_t *pu8IPAddress = (u8_t *)pvMsg; + struct in_addr addr; + u8_t i; + + /* Connected and got IP address*/ + SYS_LOG_INF("Wi-Fi connected, IP is %u.%u.%u.%u", + pu8IPAddress[0], pu8IPAddress[1], + pu8IPAddress[2], pu8IPAddress[3]); + + /* TODO at this point the standby mode should be enable + * status = WiFi connected IP assigned + */ + for (i = 0; i < 4; i++) { + addr.s4_addr[i] = pu8IPAddress[i]; + } + + /* TODO fill in net mask, gateway and lease time */ + + net_if_ipv4_addr_add(w1500_data.iface, &addr, NET_ADDR_DHCP, 0); +} + static void winc1500_wifi_cb(u8_t message_type, void *pvMsg) { SYS_LOG_INF("Msg Type %d %s", @@ -598,54 +639,151 @@ static void winc1500_wifi_cb(u8_t message_type, void *pvMsg) switch (message_type) { case M2M_WIFI_RESP_CON_STATE_CHANGED: - { - tstrM2mWifiStateChanged *pstrWifiState = - (tstrM2mWifiStateChanged *)pvMsg; - - switch (pstrWifiState->u8CurrState) { - case M2M_WIFI_DISCONNECTED: - /* TODO status disconnected */ - break; - case M2M_WIFI_CONNECTED: - /* TODO status connected */ - break; - case M2M_WIFI_UNDEF: - /* TODO status undefined*/ - break; - } + handle_wifi_con_state_changed(pvMsg); + break; + case M2M_WIFI_REQ_DHCP_CONF: + handle_wifi_dhcp_conf(pvMsg); + break; + default: + break; } - break; +} - case M2M_WIFI_REQ_DHCP_CONF: - { - u8_t *pu8IPAddress = (u8_t *)pvMsg; - struct in_addr addr; - u8_t i; - - /* Connected and got IP address*/ - SYS_LOG_INF("Wi-Fi connected, IP is %u.%u.%u.%u", - pu8IPAddress[0], pu8IPAddress[1], - pu8IPAddress[2], pu8IPAddress[3]); - /* TODO at this point the standby mode should be enable - * status = WiFi connected IP assigned - */ - for (i = 0; i < 4; i++) { - addr.s4_addr[i] = pu8IPAddress[i]; +static void handle_socket_msg_connect(struct socket_data *sd, void *pvMsg) +{ + tstrSocketConnectMsg *strConnMsg = (tstrSocketConnectMsg *)pvMsg; + + SYS_LOG_ERR("CONNECT: socket %d error %d", + strConnMsg->sock, strConnMsg->s8Error); + + if (sd->connect_cb) { + sd->connect_cb(sd->context, + strConnMsg->s8Error, + sd->connect_user_data); + } + + sd->ret_code = strConnMsg->s8Error; +} + + +static bool handle_socket_msg_recv(SOCKET sock, + struct socket_data *sd, void *pvMsg) +{ + tstrSocketRecvMsg *pstrRx = (tstrSocketRecvMsg *)pvMsg; + + if ((pstrRx->pu8Buffer != NULL) && (pstrRx->s16BufferSize > 0)) { + + net_buf_add(sd->pkt_buf, pstrRx->s16BufferSize); + + net_pkt_set_appdata(sd->rx_pkt, sd->pkt_buf->data); + net_pkt_set_appdatalen(sd->rx_pkt, pstrRx->s16BufferSize); + + if (sd->recv_cb) { + sd->recv_cb(sd->context, + sd->rx_pkt, + 0, + sd->recv_user_data); + } + } else if (pstrRx->pu8Buffer == NULL) { + if (pstrRx->s16BufferSize == SOCK_ERR_CONN_ABORTED) { + net_pkt_unref(sd->rx_pkt); + return false; } + } + + if (prepare_pkt(sd)) { + SYS_LOG_ERR("Could not reserve packet buffer"); + return false; + } + + recv(sock, sd->pkt_buf->data, + CONFIG_WIFI_WINC1500_MAX_PACKET_SIZE, K_NO_WAIT); + + return true; +} + +static void handle_socket_msg_bind(struct socket_data *sd, void *pvMsg) +{ + tstrSocketBindMsg *bind_msg = (tstrSocketBindMsg *)pvMsg; - /* TODO fill in net mask, gateway and lease time */ + /* Holding a value of ZERO for a successful bind or otherwise + * a negative error code corresponding to the type of error. + */ - net_if_ipv4_addr_add(w1500_data.iface, - &addr, NET_ADDR_DHCP, 0); + if (bind_msg->status) { + SYS_LOG_ERR("BIND: error %d %s", + bind_msg->status, + socket_message_to_string(bind_msg->status)); + sd->ret_code = bind_msg->status; } +} - break; +static void handle_socket_msg_listen(struct socket_data *sd, void *pvMsg) +{ + tstrSocketListenMsg *listen_msg = (tstrSocketListenMsg *)pvMsg; - default: - break; + /* Holding a value of ZERO for a successful listen or otherwise + * a negative error code corresponding to the type of error. + */ + + if (listen_msg->status) { + SYS_LOG_ERR("winc1500_socket_cb:LISTEN: error %d %s", + listen_msg->status, + socket_message_to_string(listen_msg->status)); + sd->ret_code = listen_msg->status; + } +} + +static void handle_socket_msg_accept(struct socket_data *sd, void *pvMsg) +{ + tstrSocketAcceptMsg *accept_msg = (tstrSocketAcceptMsg *)pvMsg; + + /* On a successful accept operation, the return information is + * the socket ID for the accepted connection with the remote peer. + * Otherwise a negative error code is returned to indicate failure + * of the accept operation. + */ + + SYS_LOG_INF("ACCEPT: from %d.%d.%d.%d:%d, new socket is %d", + accept_msg->strAddr.sin_addr.s4_addr[0], + accept_msg->strAddr.sin_addr.s4_addr[1], + accept_msg->strAddr.sin_addr.s4_addr[2], + accept_msg->strAddr.sin_addr.s4_addr[3], + ntohs(accept_msg->strAddr.sin_port), + accept_msg->sock); + + if (accept_msg->sock < 0) { + SYS_LOG_ERR("ACCEPT: error %d %s", + accept_msg->sock, + socket_message_to_string(accept_msg->sock)); + sd->ret_code = accept_msg->sock; } + if (sd->accept_cb) { + struct socket_data *a_sd; + int ret; + + a_sd = &w1500_data.socket_data[accept_msg->sock]; + + memcpy(a_sd, sd, sizeof(struct socket_data)); + + ret = net_context_get(AF_INET, SOCK_STREAM, + IPPROTO_TCP, &a_sd->context); + if (ret < 0) { + SYS_LOG_ERR("Cannot get new net context for ACCEPT"); + } else { + a_sd->context->user_data = + (void *)((int)accept_msg->sock); + + sd->accept_cb(a_sd->context, + (struct sockaddr *)&accept_msg->strAddr, + sizeof(struct sockaddr_in), + (accept_msg->sock > 0) ? + 0 : accept_msg->sock, + sd->accept_user_data); + } + } } static void winc1500_socket_cb(SOCKET sock, uint8 message, void *pvMsg) @@ -661,156 +799,32 @@ static void winc1500_socket_cb(SOCKET sock, uint8 message, void *pvMsg) switch (message) { case SOCKET_MSG_CONNECT: - { - tstrSocketConnectMsg *strConnMsg = - (tstrSocketConnectMsg *)pvMsg; - - SYS_LOG_ERR("CONNECT: socket %d error %d", - strConnMsg->sock, strConnMsg->s8Error); - - if (sd->connect_cb) { - sd->connect_cb(sd->context, - strConnMsg->s8Error, - sd->connect_user_data); - } - - sd->ret_code = strConnMsg->s8Error; - } + handle_socket_msg_connect(sd, pvMsg); k_sem_give(&sd->wait_sem); - break; + break; case SOCKET_MSG_SEND: break; - case SOCKET_MSG_RECV: - { - tstrSocketRecvMsg *pstrRx = (tstrSocketRecvMsg *)pvMsg; - - if ((pstrRx->pu8Buffer != NULL) && - (pstrRx->s16BufferSize > 0)) { - - net_buf_add(sd->pkt_buf, - pstrRx->s16BufferSize); - - net_pkt_set_appdata(sd->rx_pkt, - sd->pkt_buf->data); - net_pkt_set_appdatalen(sd->rx_pkt, - pstrRx->s16BufferSize); - - if (sd->recv_cb) { - sd->recv_cb(sd->context, - sd->rx_pkt, - 0, - sd->recv_user_data); - } - } else if (pstrRx->pu8Buffer == NULL) { - if (pstrRx->s16BufferSize == SOCK_ERR_CONN_ABORTED) { - net_pkt_unref(sd->rx_pkt); - return; - } - } - - if (prepare_pkt(&w1500_data.socket_data[sock])) { - SYS_LOG_ERR("Could not reserve packet buffer"); + if (!handle_socket_msg_recv(sock, sd, pvMsg)) { return; } - recv(sock, sd->pkt_buf->data, - CONFIG_WIFI_WINC1500_MAX_PACKET_SIZE, K_NO_WAIT); - } break; case SOCKET_MSG_BIND: - { - /* The result of the bind operation. - * Holding a value of ZERO for a successful - * bind or otherwise a negative error code - * corresponding to the type of error. - */ - tstrSocketBindMsg *bind_msg = (tstrSocketBindMsg *)pvMsg; - - if (bind_msg->status) { - SYS_LOG_ERR("BIND: error %d %s", - bind_msg->status, - socket_message_to_string(bind_msg->status)); - sd->ret_code = bind_msg->status; - } - } + handle_socket_msg_bind(sd, pvMsg); k_sem_give(&sd->wait_sem); + break; case SOCKET_MSG_LISTEN: - { - /* Holding a value of ZERO for a successful listen or - * otherwise a negative error code corresponding to - * the type of error. - */ - tstrSocketListenMsg *listen_msg = (tstrSocketListenMsg *)pvMsg; - - if (listen_msg->status) { - SYS_LOG_ERR("winc1500_socket_cb:LISTEN: error %d %s\n", - listen_msg->status, - socket_message_to_string(listen_msg->status)); - sd->ret_code = listen_msg->status; - } - } + handle_socket_msg_listen(sd, pvMsg); k_sem_give(&sd->wait_sem); + break; case SOCKET_MSG_ACCEPT: - { - /* sock - * On a successful accept operation, the return information - * is the socket ID for the accepted connection with the - * remote peer. - * Otherwise a negative error code is returned to indicate - * failure of the accept operation. - * strAddr; - * Socket address structure for the remote peer. - */ - tstrSocketAcceptMsg *accept_msg = (tstrSocketAcceptMsg *)pvMsg; - - SYS_LOG_INF("ACCEPT:" - "from %d.%d.%d.%d:%d, new socket is %d", - accept_msg->strAddr.sin_addr.s4_addr[0], - accept_msg->strAddr.sin_addr.s4_addr[1], - accept_msg->strAddr.sin_addr.s4_addr[2], - accept_msg->strAddr.sin_addr.s4_addr[3], - ntohs(accept_msg->strAddr.sin_port), - accept_msg->sock); - - if (accept_msg->sock < 0) { - SYS_LOG_ERR("ACCEPT: error %d %s", - accept_msg->sock, - socket_message_to_string(accept_msg->sock)); - sd->ret_code = accept_msg->sock; - } - - if (sd->accept_cb) { - struct socket_data *a_sd; - int ret; - - a_sd = &w1500_data.socket_data[accept_msg->sock]; - - memcpy(a_sd, sd, sizeof(struct socket_data)); - - ret = net_context_get(AF_INET, SOCK_STREAM, - IPPROTO_TCP, &a_sd->context); - if (ret < 0) { - SYS_LOG_ERR("Cannot get new network" - "context for ACCEPT"); - } else { - a_sd->context->user_data = - (void *)((int)accept_msg->sock); - - sd->accept_cb( - a_sd->context, - (struct sockaddr *)&accept_msg->strAddr, - sizeof(struct sockaddr_in), - (accept_msg->sock > 0) ? - 0 :accept_msg->sock, - sd->accept_user_data); - } - } - } + handle_socket_msg_accept(sd, pvMsg); k_sem_give(&sd->wait_sem); + break; } } From f60b62fb1b56c9b5c081abab90fd8a2b43130089 Mon Sep 17 00:00:00 2001 From: Tomasz Bursztyka Date: Wed, 15 Nov 2017 13:30:38 +0100 Subject: [PATCH 08/13] drivers/wifi: Switch info level to debug level in winc1500 driver These output are fine while debugging, but useless otherwise. Signed-off-by: Tomasz Bursztyka --- drivers/wifi/wifi_winc1500.c | 33 ++++++++++++++++----- drivers/wifi/wifi_winc1500_nm_bus_wrapper.c | 2 +- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/drivers/wifi/wifi_winc1500.c b/drivers/wifi/wifi_winc1500.c index 1ae0989076bb6..dcdcd6c926c68 100644 --- a/drivers/wifi/wifi_winc1500.c +++ b/drivers/wifi/wifi_winc1500.c @@ -6,6 +6,10 @@ #define SYS_LOG_LEVEL CONFIG_SYS_LOG_WIFI_LEVEL #define SYS_LOG_DOMAIN "dev/winc1500" +#if (SYS_LOG_LEVEL > SYS_LOG_LEVEL_OFF) +#define NET_LOG_ENABLED 1 +#endif + #include #include @@ -144,6 +148,13 @@ static struct winc1500_data w1500_data; #if (SYS_LOG_LEVEL > SYS_LOG_LEVEL_OFF) +static void stack_stats(void) +{ + net_analyze_stack("WINC1500 stack", + K_THREAD_STACK_BUFFER(winc1500_stack), + K_THREAD_STACK_SIZEOF(winc1500_stack)); +} + static char *socket_error_string(s8_t err) { switch (err) { @@ -599,12 +610,15 @@ static void handle_wifi_con_state_changed(void *pvMsg) switch (pstrWifiState->u8CurrState) { case M2M_WIFI_DISCONNECTED: /* TODO status disconnected */ + SYS_LOG_DBG("Disconnected"); break; case M2M_WIFI_CONNECTED: /* TODO status connected */ + SYS_LOG_DBG("Connected"); break; case M2M_WIFI_UNDEF: /* TODO status undefined*/ + SYS_LOG_DBG("Undefined?"); break; } } @@ -616,7 +630,7 @@ static void handle_wifi_dhcp_conf(void *pvMsg) u8_t i; /* Connected and got IP address*/ - SYS_LOG_INF("Wi-Fi connected, IP is %u.%u.%u.%u", + SYS_LOG_DBG("Wi-Fi connected, IP is %u.%u.%u.%u", pu8IPAddress[0], pu8IPAddress[1], pu8IPAddress[2], pu8IPAddress[3]); @@ -634,7 +648,7 @@ static void handle_wifi_dhcp_conf(void *pvMsg) static void winc1500_wifi_cb(u8_t message_type, void *pvMsg) { - SYS_LOG_INF("Msg Type %d %s", + SYS_LOG_DBG("Msg Type %d %s", message_type, wifi_cb_msg_2_str(message_type)); switch (message_type) { @@ -648,6 +662,7 @@ static void winc1500_wifi_cb(u8_t message_type, void *pvMsg) break; } + stack_stats(); } static void handle_socket_msg_connect(struct socket_data *sd, void *pvMsg) @@ -745,7 +760,7 @@ static void handle_socket_msg_accept(struct socket_data *sd, void *pvMsg) * of the accept operation. */ - SYS_LOG_INF("ACCEPT: from %d.%d.%d.%d:%d, new socket is %d", + SYS_LOG_DBG("ACCEPT: from %d.%d.%d.%d:%d, new socket is %d", accept_msg->strAddr.sin_addr.s4_addr[0], accept_msg->strAddr.sin_addr.s4_addr[1], accept_msg->strAddr.sin_addr.s4_addr[2], @@ -791,7 +806,7 @@ static void winc1500_socket_cb(SOCKET sock, uint8 message, void *pvMsg) struct socket_data *sd = &w1500_data.socket_data[sock]; if (message != 6) { - SYS_LOG_INF(": sock %d Msg %d %s", + SYS_LOG_DBG(": sock %d Msg %d %s", sock, message, socket_message_to_string(message)); } @@ -827,6 +842,8 @@ static void winc1500_socket_cb(SOCKET sock, uint8 message, void *pvMsg) break; } + + stack_stats(); } static void winc1500_thread(void) @@ -842,7 +859,7 @@ static void winc1500_thread(void) static void winc1500_iface_init(struct net_if *iface) { - SYS_LOG_INF("eth_init:net_if_set_link_addr:" + SYS_LOG_DBG("eth_init:net_if_set_link_addr:" "MAC Address %02X:%02X:%02X:%02X:%02X:%02X", w1500_data.mac[0], w1500_data.mac[1], w1500_data.mac[2], w1500_data.mac[3], w1500_data.mac[4], w1500_data.mac[5]); @@ -882,7 +899,7 @@ static int winc1500_init(struct device *dev) registerSocketCallback(winc1500_socket_cb, NULL); m2m_wifi_get_otp_mac_address(w1500_data.mac, &is_valid); - SYS_LOG_INF("WINC1500 MAC Address from OTP (%d) " + SYS_LOG_DBG("WINC1500 MAC Address from OTP (%d) " "%02X:%02X:%02X:%02X:%02X:%02X", is_valid, w1500_data.mac[0], w1500_data.mac[1], w1500_data.mac[2], @@ -898,7 +915,7 @@ static int winc1500_init(struct device *dev) K_PRIO_COOP(CONFIG_WIFI_WINC1500_THREAD_PRIO), 0, K_NO_WAIT); - SYS_LOG_INF("Connecting to %s (%u) with %s", + SYS_LOG_DBG("Connecting to %s (%u) with %s", CONFIG_WIFI_WINC1500_SSID, CONFIG_WIFI_WINC1500_SSID_LENGTH, CONFIG_WIFI_WINC1500_PSK); @@ -911,7 +928,7 @@ static int winc1500_init(struct device *dev) SYS_LOG_WRN("Connecting to wifi does not seem to work"); } - SYS_LOG_INF("WINC1500 driver Initialized"); + SYS_LOG_DBG("WINC1500 driver Initialized"); return 0; } diff --git a/drivers/wifi/wifi_winc1500_nm_bus_wrapper.c b/drivers/wifi/wifi_winc1500_nm_bus_wrapper.c index 230f36d044d90..f0ff133d40e1b 100644 --- a/drivers/wifi/wifi_winc1500_nm_bus_wrapper.c +++ b/drivers/wifi/wifi_winc1500_nm_bus_wrapper.c @@ -130,7 +130,7 @@ s8_t nm_bus_init(void *pvinit) nm_bsp_interrupt_ctrl(1); - SYS_LOG_INF("NOTICE:DONE"); + SYS_LOG_DBG("NOTICE:DONE"); #endif return 0; } From 9c1f15d242c126de440cfedab6ce065427080e11 Mon Sep 17 00:00:00 2001 From: Tomasz Bursztyka Date: Wed, 15 Nov 2017 14:26:45 +0100 Subject: [PATCH 09/13] drivers/wifi: WINC1500 driver is not using WAKE pin It does not seem to be useful atm. So let's remove it. Signed-off-by: Tomasz Bursztyka --- include/drivers/wifi/winc1500.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/drivers/wifi/winc1500.h b/include/drivers/wifi/winc1500.h index ea824fabb5923..0f7c7e0f0812e 100644 --- a/include/drivers/wifi/winc1500.h +++ b/include/drivers/wifi/winc1500.h @@ -8,7 +8,6 @@ enum winc1500_gpio_index { WINC1500_GPIO_IDX_CHIP_EN = 0, - WINC1500_GPIO_IDX_WAKE, WINC1500_GPIO_IDX_IRQN, WINC1500_GPIO_IDX_RESET_N, From 2baa1d57a51c43951cc61d2453a61ddb514e9d92 Mon Sep 17 00:00:00 2001 From: Tomasz Bursztyka Date: Thu, 7 Dec 2017 21:35:48 +0100 Subject: [PATCH 10/13] drivers/winc1500: Implement wifi mgmt offloaded API Scan, connect and disconnect for now. Signed-off-by: Tomasz Bursztyka --- drivers/wifi/Kconfig.winc1500 | 31 +++-- drivers/wifi/wifi_winc1500.c | 220 ++++++++++++++++++++++++++++++---- 2 files changed, 212 insertions(+), 39 deletions(-) diff --git a/drivers/wifi/Kconfig.winc1500 b/drivers/wifi/Kconfig.winc1500 index 1ec2a9aba498b..38d3bc605c14a 100644 --- a/drivers/wifi/Kconfig.winc1500 +++ b/drivers/wifi/Kconfig.winc1500 @@ -10,6 +10,8 @@ menuconfig WIFI_WINC1500 bool "WINC1500 driver support" default n select ATMEL_WINC1500 + select WIFI_OFFLOAD + select NET_L2_WIFI_MGMT if WIFI_WINC1500 @@ -97,24 +99,19 @@ config WIFI_WINC1500_OFFLOAD_MAX_SOCKETS Set the number of sockets that can be managed through the driver and the chip. -config WIFI_WINC1500_SSID - string "SSID the chip shall try to connect to" - default "" - help - Set the SSID you want the chip to connect to. Note: only WPA PSK - based AP is supported. Test purpose only, a full featured interface - will be used at some point for more flexible configuration. +choice + bool "In which region is the chip running?" + default WIFI_WINC1500_REGION_NORTH_AMERICA -config WIFI_WINC1500_SSID_LENGTH - int "Length of the SSID (do not count the \0)" - default 0 - help - SSID length, without counting the terminal character '\0' +config WIFI_WINC1500_REGION_NORTH_AMERICA + bool "Region North America" -config WIFI_WINC1500_PSK - string "Pre-Shared Key (human readable)" - default "" - help - Set the PSK for the given SSID. +config WIFI_WINC1500_REGION_EUROPE + bool "Region Europe" + +config WIFI_WINC1500_REGION_ASIA + bool "Region Asia" + +endchoice endif # WIFI_WINC1500 diff --git a/drivers/wifi/wifi_winc1500.c b/drivers/wifi/wifi_winc1500.c index dcdcd6c926c68..e9d6dd20a19a8 100644 --- a/drivers/wifi/wifi_winc1500.c +++ b/drivers/wifi/wifi_winc1500.c @@ -22,6 +22,7 @@ #include #include #include +#include #include @@ -110,6 +111,14 @@ typedef struct { #include #include +#if defined(CONFIG_WIFI_WINC1500_REGION_NORTH_AMERICA) +#define WINC1500_REGION NORTH_AMERICA +#elif defined(CONFIG_WIFI_WINC1500_REGION_EUROPE) +#define WINC1500_REGION EUROPE +#elif defined(CONFIG_WIFI_WINC1500_REGION_ASIA) +#define WINC1500_REGION ASIA +#endif + #define WINC1500_BIND_TIMEOUT 500 #define WINC1500_LISTEN_TIMEOUT 500 @@ -142,6 +151,10 @@ struct winc1500_data { CONFIG_WIFI_WINC1500_OFFLOAD_MAX_SOCKETS]; struct net_if *iface; unsigned char mac[6]; + scan_result_cb_t scan_cb; + u8_t scan_result; + bool connecting; + bool connected; }; static struct winc1500_data w1500_data; @@ -609,12 +622,26 @@ static void handle_wifi_con_state_changed(void *pvMsg) switch (pstrWifiState->u8CurrState) { case M2M_WIFI_DISCONNECTED: - /* TODO status disconnected */ - SYS_LOG_DBG("Disconnected"); + SYS_LOG_DBG("Disconnected (%u)", pstrWifiState->u8ErrCode); + + if (w1500_data.connecting) { + wifi_mgmt_raise_connect_result_event(w1500_data.iface, + pstrWifiState->u8ErrCode ? -EIO : 0); + w1500_data.connecting = false; + + break; + } + + w1500_data.connected = false; + wifi_mgmt_raise_disconnect_result_event(w1500_data.iface, 0); + break; case M2M_WIFI_CONNECTED: - /* TODO status connected */ - SYS_LOG_DBG("Connected"); + SYS_LOG_DBG("Connected (%u)", pstrWifiState->u8ErrCode); + + w1500_data.connected = true; + wifi_mgmt_raise_connect_result_event(w1500_data.iface, 0); + break; case M2M_WIFI_UNDEF: /* TODO status undefined*/ @@ -646,6 +673,84 @@ static void handle_wifi_dhcp_conf(void *pvMsg) net_if_ipv4_addr_add(w1500_data.iface, &addr, NET_ADDR_DHCP, 0); } +static void reset_scan_data(void) +{ + w1500_data.scan_cb = NULL; + w1500_data.scan_result = 0; +} + +static void handle_scan_result(void *pvMsg) +{ + tstrM2mWifiscanResult *pstrScanResult = (tstrM2mWifiscanResult *)pvMsg; + struct wifi_scan_result result; + + if (!w1500_data.scan_cb) { + return; + } + + if (pstrScanResult->u8AuthType == M2M_WIFI_SEC_OPEN) { + result.security = WIFI_SECURITY_TYPE_NONE; + } else if (pstrScanResult->u8AuthType == M2M_WIFI_SEC_WPA_PSK) { + result.security = WIFI_SECURITY_TYPE_PSK; + } else { + SYS_LOG_DBG("Security %u not supported", + pstrScanResult->u8AuthType); + goto out; + } + + memcpy(result.ssid, pstrScanResult->au8SSID, WIFI_SSID_MAX_LEN); + result.ssid_length = strlen(result.ssid); + + result.channel = pstrScanResult->u8ch; + result.rssi = pstrScanResult->s8rssi; + + w1500_data.scan_cb(w1500_data.iface, 0, &result); + + k_yield(); + +out: + if (w1500_data.scan_result < m2m_wifi_get_num_ap_found()) { + m2m_wifi_req_scan_result(w1500_data.scan_result); + w1500_data.scan_result++; + } else { + w1500_data.scan_cb(w1500_data.iface, 0, NULL); + reset_scan_data(); + } +} + +static void handle_scan_done(void *pvMsg) +{ + tstrM2mScanDone *pstrInfo = (tstrM2mScanDone *)pvMsg; + + if (!w1500_data.scan_cb) { + return; + } + + if (pstrInfo->s8ScanState != M2M_SUCCESS) { + w1500_data.scan_cb(w1500_data.iface, -EIO, NULL); + reset_scan_data(); + + SYS_LOG_ERR("Scan failed."); + + return; + } + + w1500_data.scan_result = 0; + + if (pstrInfo->u8NumofCh >= 1) { + SYS_LOG_DBG("Requesting results (%u)", + m2m_wifi_get_num_ap_found()); + + m2m_wifi_req_scan_result(w1500_data.scan_result); + w1500_data.scan_result++; + } else { + SYS_LOG_DBG("No AP found"); + + w1500_data.scan_cb(w1500_data.iface, 0, NULL); + reset_scan_data(); + } +} + static void winc1500_wifi_cb(u8_t message_type, void *pvMsg) { SYS_LOG_DBG("Msg Type %d %s", @@ -658,6 +763,12 @@ static void winc1500_wifi_cb(u8_t message_type, void *pvMsg) case M2M_WIFI_REQ_DHCP_CONF: handle_wifi_dhcp_conf(pvMsg); break; + case M2M_WIFI_RESP_SCAN_RESULT: + handle_scan_result(pvMsg); + break; + case M2M_WIFI_RESP_SCAN_DONE: + handle_scan_done(pvMsg); + break; default: break; } @@ -856,6 +967,79 @@ static void winc1500_thread(void) } } +static int winc1500_mgmt_scan(struct device *dev, scan_result_cb_t cb) +{ + if (w1500_data.scan_cb) { + return -EALREADY; + } + + w1500_data.scan_cb = cb; + + if (m2m_wifi_request_scan(M2M_WIFI_CH_ALL)) { + w1500_data.scan_cb = NULL; + return -EIO; + } + + return 0; +} + +static int winc1500_mgmt_connect(struct device *dev, + struct wifi_connect_req_params *params) +{ + u8_t ssid[M2M_MAX_SSID_LEN]; + tuniM2MWifiAuth psk; + u8_t security; + u16_t channel; + void *auth; + + memcpy(ssid, params->ssid, params->ssid_length); + ssid[params->ssid_length] = '\0'; + + if (params->security == WIFI_SECURITY_TYPE_PSK) { + memcpy(psk.au8PSK, params->psk, params->psk_length); + psk.au8PSK[params->psk_length] = '\0'; + auth = &psk; + + security = M2M_WIFI_SEC_WPA_PSK; + } else { + auth = NULL; + security = M2M_WIFI_SEC_OPEN; + } + + if (params->channel == WIFI_CHANNEL_ANY) { + channel = M2M_WIFI_CH_ALL; + } else { + channel = params->channel; + } + + SYS_LOG_DBG("Connecting to %s (%u) on channel %u %s security (%s)", + ssid, params->ssid_length, + channel == M2M_WIFI_CH_ALL ? "unknown" : channel, + security == M2M_WIFI_SEC_OPEN ? "without" : "with", + params->psk ? (char *)psk.au8PSK : ""); + + if (m2m_wifi_connect((char *)ssid, params->ssid_length, + security, auth, channel)) { + return -EIO; + } + + w1500_data.connecting = true; + + return 0; +} + +static int winc1500_mgmt_disconnect(struct device *device) +{ + if (!w1500_data.connected) { + return -EALREADY; + } + + if (m2m_wifi_disconnect()) { + return -EIO; + } + + return 0; +} static void winc1500_iface_init(struct net_if *iface) { @@ -872,8 +1056,11 @@ static void winc1500_iface_init(struct net_if *iface) w1500_data.iface = iface; } -static const struct net_if_api winc1500_api = { - .init = winc1500_iface_init, +static const struct net_wifi_mgmt_offload winc1500_api = { + .iface_api.init = winc1500_iface_init, + .scan = winc1500_mgmt_scan, + .connect = winc1500_mgmt_connect, + .disconnect = winc1500_mgmt_disconnect, }; static int winc1500_init(struct device *dev) @@ -881,20 +1068,22 @@ static int winc1500_init(struct device *dev) tstrWifiInitParam param = { .pfAppWifiCb = winc1500_wifi_cb, }; - tuniM2MWifiAuth creds = { - .au8PSK = CONFIG_WIFI_WINC1500_PSK, - }; unsigned char is_valid; int ret; ARG_UNUSED(dev); + w1500_data.connecting = false; + w1500_data.connected = false; + ret = m2m_wifi_init(¶m); if (ret) { SYS_LOG_ERR("m2m_wifi_init return error!(%d)", ret); return -EIO; } + m2m_wifi_set_scan_region(WINC1500_REGION); + socketInit(); registerSocketCallback(winc1500_socket_cb, NULL); @@ -915,19 +1104,6 @@ static int winc1500_init(struct device *dev) K_PRIO_COOP(CONFIG_WIFI_WINC1500_THREAD_PRIO), 0, K_NO_WAIT); - SYS_LOG_DBG("Connecting to %s (%u) with %s", - CONFIG_WIFI_WINC1500_SSID, - CONFIG_WIFI_WINC1500_SSID_LENGTH, - CONFIG_WIFI_WINC1500_PSK); - - ret = m2m_wifi_connect(CONFIG_WIFI_WINC1500_SSID, - CONFIG_WIFI_WINC1500_SSID_LENGTH, - M2M_WIFI_SEC_WPA_PSK, &creds, - M2M_WIFI_CH_ALL); - if (ret) { - SYS_LOG_WRN("Connecting to wifi does not seem to work"); - } - SYS_LOG_DBG("WINC1500 driver Initialized"); return 0; From 0da2bfc3587e357f7f2f46c6e6e47f434e7c7af0 Mon Sep 17 00:00:00 2001 From: Tomasz Bursztyka Date: Tue, 20 Mar 2018 11:18:53 +0100 Subject: [PATCH 11/13] drivers/wifi: Move all winc1500 related code to its own directory There will be other drivers, and mixing up all these files together will create a mess so better having a dedicated place for winc1500, at least. Signed-off-by: Tomasz Bursztyka --- drivers/wifi/CMakeLists.txt | 10 +--------- drivers/wifi/Kconfig | 2 +- drivers/wifi/winc1500/CMakeLists.txt | 9 +++++++++ drivers/wifi/{ => winc1500}/Kconfig.winc1500 | 0 drivers/wifi/{ => winc1500}/wifi_winc1500.c | 0 drivers/wifi/{ => winc1500}/wifi_winc1500_config.h | 0 drivers/wifi/{ => winc1500}/wifi_winc1500_nm_bsp.c | 0 .../{ => winc1500}/wifi_winc1500_nm_bsp_internal.h | 0 .../wifi/{ => winc1500}/wifi_winc1500_nm_bus_wrapper.c | 0 9 files changed, 11 insertions(+), 10 deletions(-) create mode 100644 drivers/wifi/winc1500/CMakeLists.txt rename drivers/wifi/{ => winc1500}/Kconfig.winc1500 (100%) rename drivers/wifi/{ => winc1500}/wifi_winc1500.c (100%) rename drivers/wifi/{ => winc1500}/wifi_winc1500_config.h (100%) rename drivers/wifi/{ => winc1500}/wifi_winc1500_nm_bsp.c (100%) rename drivers/wifi/{ => winc1500}/wifi_winc1500_nm_bsp_internal.h (100%) rename drivers/wifi/{ => winc1500}/wifi_winc1500_nm_bus_wrapper.c (100%) diff --git a/drivers/wifi/CMakeLists.txt b/drivers/wifi/CMakeLists.txt index a97b419ee23ab..e64114949ef8d 100644 --- a/drivers/wifi/CMakeLists.txt +++ b/drivers/wifi/CMakeLists.txt @@ -1,9 +1 @@ -if(CONFIG_WIFI_WINC1500) - zephyr_include_directories(./) - - zephyr_sources( - wifi_winc1500_nm_bsp.c - wifi_winc1500_nm_bus_wrapper.c - wifi_winc1500.c - ) -endif() +add_subdirectory_ifdef(CONFIG_WIFI_WINC1500 winc1500) diff --git a/drivers/wifi/Kconfig b/drivers/wifi/Kconfig index 731e684726e1b..369a144d24a55 100644 --- a/drivers/wifi/Kconfig +++ b/drivers/wifi/Kconfig @@ -43,6 +43,6 @@ config WIFI_OFFLOAD help Enable support for Full-MAC WiFi devices. -source "drivers/wifi/Kconfig.winc1500" +source "drivers/wifi/winc1500/Kconfig.winc1500" endif # WIFI diff --git a/drivers/wifi/winc1500/CMakeLists.txt b/drivers/wifi/winc1500/CMakeLists.txt new file mode 100644 index 0000000000000..a97b419ee23ab --- /dev/null +++ b/drivers/wifi/winc1500/CMakeLists.txt @@ -0,0 +1,9 @@ +if(CONFIG_WIFI_WINC1500) + zephyr_include_directories(./) + + zephyr_sources( + wifi_winc1500_nm_bsp.c + wifi_winc1500_nm_bus_wrapper.c + wifi_winc1500.c + ) +endif() diff --git a/drivers/wifi/Kconfig.winc1500 b/drivers/wifi/winc1500/Kconfig.winc1500 similarity index 100% rename from drivers/wifi/Kconfig.winc1500 rename to drivers/wifi/winc1500/Kconfig.winc1500 diff --git a/drivers/wifi/wifi_winc1500.c b/drivers/wifi/winc1500/wifi_winc1500.c similarity index 100% rename from drivers/wifi/wifi_winc1500.c rename to drivers/wifi/winc1500/wifi_winc1500.c diff --git a/drivers/wifi/wifi_winc1500_config.h b/drivers/wifi/winc1500/wifi_winc1500_config.h similarity index 100% rename from drivers/wifi/wifi_winc1500_config.h rename to drivers/wifi/winc1500/wifi_winc1500_config.h diff --git a/drivers/wifi/wifi_winc1500_nm_bsp.c b/drivers/wifi/winc1500/wifi_winc1500_nm_bsp.c similarity index 100% rename from drivers/wifi/wifi_winc1500_nm_bsp.c rename to drivers/wifi/winc1500/wifi_winc1500_nm_bsp.c diff --git a/drivers/wifi/wifi_winc1500_nm_bsp_internal.h b/drivers/wifi/winc1500/wifi_winc1500_nm_bsp_internal.h similarity index 100% rename from drivers/wifi/wifi_winc1500_nm_bsp_internal.h rename to drivers/wifi/winc1500/wifi_winc1500_nm_bsp_internal.h diff --git a/drivers/wifi/wifi_winc1500_nm_bus_wrapper.c b/drivers/wifi/winc1500/wifi_winc1500_nm_bus_wrapper.c similarity index 100% rename from drivers/wifi/wifi_winc1500_nm_bus_wrapper.c rename to drivers/wifi/winc1500/wifi_winc1500_nm_bus_wrapper.c From 9ef6abd713624aafd1cb23dfa7c0a25ef91f936e Mon Sep 17 00:00:00 2001 From: Tomasz Bursztyka Date: Wed, 27 Sep 2017 15:22:40 +0200 Subject: [PATCH 12/13] samples/net: Add a simple sample to run wifi shell module Enabling relevant hardware, currently only winc1500 on quark_se_c1000_devboard. But it could be easily extended to other drivers/boards. Signed-off-by: Tomasz Bursztyka --- samples/net/wifi/CMakeLists.txt | 17 ++++++ samples/net/wifi/Kconfig | 23 ++++++++ samples/net/wifi/README.rst | 49 +++++++++++++++++ .../wifi/boards/quark_se_c1000_devboard.conf | 17 ++++++ samples/net/wifi/prj_base.conf | 36 +++++++++++++ samples/net/wifi/src/wifi_test.c | 52 +++++++++++++++++++ 6 files changed, 194 insertions(+) create mode 100644 samples/net/wifi/CMakeLists.txt create mode 100644 samples/net/wifi/Kconfig create mode 100644 samples/net/wifi/README.rst create mode 100644 samples/net/wifi/boards/quark_se_c1000_devboard.conf create mode 100644 samples/net/wifi/prj_base.conf create mode 100644 samples/net/wifi/src/wifi_test.c diff --git a/samples/net/wifi/CMakeLists.txt b/samples/net/wifi/CMakeLists.txt new file mode 100644 index 0000000000000..aaba52921c1cd --- /dev/null +++ b/samples/net/wifi/CMakeLists.txt @@ -0,0 +1,17 @@ +set(KCONFIG_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/Kconfig) + +macro(set_conf_file) + if(EXISTS ${APPLICATION_SOURCE_DIR}/prj_${BOARD}.conf) + set(CONF_FILE "${APPLICATION_SOURCE_DIR}/prj_${BOARD}.conf") + elseif(EXISTS ${APPLICATION_SOURCE_DIR}/boards/${BOARD}.conf) + set(CONF_FILE "prj_base.conf ${APPLICATION_SOURCE_DIR}/boards/${BOARD}.conf") + else() + set(CONF_FILE "prj_base.conf") + endif() +endmacro() + +include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE) +project(NONE) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/samples/net/wifi/Kconfig b/samples/net/wifi/Kconfig new file mode 100644 index 0000000000000..ae4759391b148 --- /dev/null +++ b/samples/net/wifi/Kconfig @@ -0,0 +1,23 @@ +mainmenu "Wi-Fi sample" + +config ZEPHYR_BASE + string + option env="ZEPHYR_BASE" + +source "$ZEPHYR_BASE/Kconfig.zephyr" + +if WIFI_WINC1500 + +config WINC1500_GPIO_DRV_NAME + string "GPIO device name" + +config WINC1500_GPIO_CHIP_EN + int "Pin number for Winc1500 CHIP_EN signal" + +config WINC1500_GPIO_IRQN + int "Pin number for Winc1500 IRQn signal" + +config WINC1500_GPIO_RESET_N + int "Pin number for Winc1500 RESET_N signal" + +endif # WIFI_WINC1500 diff --git a/samples/net/wifi/README.rst b/samples/net/wifi/README.rst new file mode 100644 index 0000000000000..28980e5a3e5d8 --- /dev/null +++ b/samples/net/wifi/README.rst @@ -0,0 +1,49 @@ +.. _wifi_sample: + +Wi-Fi sample +############ + +Overview +******** + +This sample allows testing Wi-Fi drivers for various boards by +enabling the Wi-Fi shell module that provides a set of commands: +scan, connect, and disconnect. It also enables the net_shell module +to verify net_if settings. + +Building and Running +******************** + +Verify the board and chip you are targeting provide Wi-Fi support. + +For instance, Atmel's Winc1500 chip is supported on top of +quark_se_c1000_devboard board. + +.. zephyr-app-commands:: + :zephyr-app: samples/net/wifi + :board: quark_se_c1000_devboard + :goals: build + :compact: + +Sample console interaction +========================== + +.. code-block:: console + + shell> select wifi + wifi> scan + Scan requested + wifi> + Num | SSID (len) | Chan | RSSI | Sec + 1 | kapoueh! 8 | 1 | -93 | WPA/WPA2 + 2 | mooooooh 8 | 6 | -89 | WPA/WPA2 + 3 | Ap-foo blob.. 13 | 11 | -73 | WPA/WPA2 + 4 | gksu 4 | 1 | -26 | WPA/WPA2 + ---------- + Scan request done + + wifi> connect "gksu" 4 SecretStuff + Connection requested + wifi> + Connected + wifi> diff --git a/samples/net/wifi/boards/quark_se_c1000_devboard.conf b/samples/net/wifi/boards/quark_se_c1000_devboard.conf new file mode 100644 index 0000000000000..56e8e045a2669 --- /dev/null +++ b/samples/net/wifi/boards/quark_se_c1000_devboard.conf @@ -0,0 +1,17 @@ +CONFIG_GPIO=y +CONFIG_SPI=y +CONFIG_SPI_LEGACY_API=n + +CONFIG_SPI_QMSI=n +CONFIG_SPI_DW=y + +CONFIG_WIFI_WINC1500=y +CONFIG_WIFI_WINC1500_REGION_EUROPE=y +CONFIG_WIFI_WINC1500_GPIO_SPI_CS=y +CONFIG_WIFI_WINC1500_GPIO_SPI_CS_DRV_NAME="GPIO_0" +CONFIG_WIFI_WINC1500_GPIO_SPI_CS_PIN=13 + +CONFIG_WINC1500_GPIO_DRV_NAME="GPIO_0" +CONFIG_WINC1500_GPIO_CHIP_EN=19 +CONFIG_WINC1500_GPIO_IRQN=18 +CONFIG_WINC1500_GPIO_RESET_N=26 \ No newline at end of file diff --git a/samples/net/wifi/prj_base.conf b/samples/net/wifi/prj_base.conf new file mode 100644 index 0000000000000..584f9d8af6f2a --- /dev/null +++ b/samples/net/wifi/prj_base.conf @@ -0,0 +1,36 @@ +CONFIG_EARLY_CONSOLE=y + +CONFIG_NETWORKING=y +CONFIG_TEST_RANDOM_GENERATOR=y + +CONFIG_NET_TX_STACK_SIZE=2048 +CONFIG_NET_RX_STACK_SIZE=2048 + +CONFIG_NET_PKT_RX_COUNT=10 +CONFIG_NET_PKT_TX_COUNT=10 +CONFIG_NET_BUF_RX_COUNT=20 +CONFIG_NET_BUF_TX_COUNT=20 +CONFIG_NET_MAX_CONTEXTS=10 + +CONFIG_NET_IPV4=y +CONFIG_NET_IPV6=n + +CONFIG_NET_LOG=y +CONFIG_SYS_LOG_NET_LEVEL=1 +CONFIG_SYS_LOG_SHOW_COLOR=y +CONFIG_INIT_STACKS=y + +CONFIG_NET_SHELL=y + +CONFIG_NET_DEBUG_CORE=n +CONFIG_NET_DEBUG_CONTEXT=n +CONFIG_NET_DEBUG_NET_PKT=n +CONFIG_NET_DEBUG_UTILS=n +CONFIG_NET_DEBUG_IF=n +CONFIG_NET_DEBUG_CONN=n +CONFIG_NET_STATISTICS=y +CONFIG_NET_STATISTICS_PERIODIC_OUTPUT=n + +CONFIG_WIFI=y +CONFIG_SYS_LOG_WIFI_LEVEL=1 +CONFIG_NET_L2_WIFI_SHELL=y diff --git a/samples/net/wifi/src/wifi_test.c b/samples/net/wifi/src/wifi_test.c new file mode 100644 index 0000000000000..f9398dd419bf9 --- /dev/null +++ b/samples/net/wifi/src/wifi_test.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#ifdef CONFIG_WIFI_WINC1500 + +#include +#include +#include + +static +struct winc1500_gpio_configuration winc1500_gpios[WINC1500_GPIO_IDX_MAX] = { + { .dev = NULL, .pin = CONFIG_WINC1500_GPIO_CHIP_EN }, + { .dev = NULL, .pin = CONFIG_WINC1500_GPIO_IRQN }, + { .dev = NULL, .pin = CONFIG_WINC1500_GPIO_RESET_N }, +}; + +struct winc1500_gpio_configuration *winc1500_configure_gpios(void) +{ + const int flags_int_in = (GPIO_DIR_IN | GPIO_INT | + GPIO_INT_ACTIVE_LOW | GPIO_INT_DEBOUNCE | + GPIO_INT_EDGE); + const int flags_noint_out = GPIO_DIR_OUT; + struct device *gpio; + + gpio = device_get_binding(CONFIG_WINC1500_GPIO_DRV_NAME); + + gpio_pin_configure(gpio, winc1500_gpios[WINC1500_GPIO_IDX_CHIP_EN].pin, + flags_noint_out); + gpio_pin_configure(gpio, winc1500_gpios[WINC1500_GPIO_IDX_IRQN].pin, + flags_int_in); + gpio_pin_configure(gpio, winc1500_gpios[WINC1500_GPIO_IDX_RESET_N].pin, + flags_noint_out); + + winc1500_gpios[WINC1500_GPIO_IDX_CHIP_EN].dev = gpio; + winc1500_gpios[WINC1500_GPIO_IDX_IRQN].dev = gpio; + winc1500_gpios[WINC1500_GPIO_IDX_RESET_N].dev = gpio; + + return winc1500_gpios; +} + +#endif /* CONFIG_WIFI_WINC1500 */ + +void main(void) +{ + k_sleep(K_FOREVER); +} From 1185148c76d486b70aaee06839005b060a78901e Mon Sep 17 00:00:00 2001 From: Tomasz Bursztyka Date: Fri, 4 May 2018 10:50:32 +0200 Subject: [PATCH 13/13] ext/hal: Add WINC1500 README for non-Apache 2.0 licensed contribution Atmel ASF is BSD-3-Clause Signed-off-by: Tomasz Bursztyka --- .../atmel/asf/common/components/wifi/README | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 ext/hal/atmel/asf/common/components/wifi/README diff --git a/ext/hal/atmel/asf/common/components/wifi/README b/ext/hal/atmel/asf/common/components/wifi/README new file mode 100644 index 0000000000000..c7095e2352b68 --- /dev/null +++ b/ext/hal/atmel/asf/common/components/wifi/README @@ -0,0 +1,55 @@ +Atmel WINC1500 HAL +################## + +Origin: + Extracted from Atmel ASF - Advanced Software Framework + Embedded Software Solution for Atmel Flash MCUs + + Took the generic winc1500 code in ASF directory: + common/components/wifi/winc1500 + + http://asf.atmel.com/docs/latest/download.html + +Status: + 3.35 + +Purpose: + Drive Atmel WINC1500 offloaded WiFi chip. + +Description: + In order to support WINC1500 chip, it has been decided to use the + existing Atmel't HAL: ASF. WINC1500 is an MCU providing WiFi and + an IPv4 stack. These features appear then fully offloaded from Zephyr + into that chip. + + Provides an acces to WiFi networks. + + Zephyr does not own a native WiFi stack, however enabling Zephyr to + access WiFi networks is critical and using such offloaded MCU is the + easiest way to achieve this goal. + + WINC1500 is fairly easy to interface with, it proposes either SPI or + I²C bus to do so. + +Dependencies: + None. + + No direct dependancy. Zephyr will see the MCU as a usual network + interface. Such object being instanciated by the driver, which in turn + accesses the chip through Atmel ASF HAL. + +URL: + http://asf.atmel.com/docs/latest/download.html + +commit: + 772047b391345f276237d1b340055045d18c3844 + +Maintained-by: + External + +License: + BSD-3-Clause + +License Link: + See last page of Release notes found at: + http://www.microchip.com/avr-support/advanced-software-framework-(asf)