Пример #1
0
//*****************************************************************************
//
//!  nvmem_get_mac_address
//!
//!  @param[out]  mac   mac address
//!
//!  @return       on success 0, error otherwise.
//!
//!  @brief       Read MAC address from EEPROM.
//!               mac address as appears over the air (OUI first)
//!
//*****************************************************************************
uint8_t c_nvmem_get_mac_address(uint8_t *mac)
{
    return  c_nvmem_read(NVMEM_MAC_FILEID, MAC_ADDR_LEN, 0, mac);
}
/*****************************************************************************
*
*  nvmem.c  - CC3000 Host Driver Implementation.
*  Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
*
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions
*  are met:
*
*    Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
*
*    Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the
*    distribution.
*
*    Neither the name of Texas Instruments Incorporated nor the names of
*    its contributors may be used to endorse or promote products derived
*    from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
*  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
*  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/

//*****************************************************************************
//
//! \addtogroup nvmem_api
//! @{
//
//*****************************************************************************

#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "evnt_handler.h"
#include "socket.h"
#include "nvmem.h"
#include "hci.h"


//*****************************************************************************
//
// Prototypes for the structures for APIs.
//
//*****************************************************************************

#define NVMEM_READ_PARAMS_LEN   (12)
#define NVMEM_CREATE_PARAMS_LEN     (8)
#define NVMEM_WRITE_PARAMS_LEN  (16)


#ifndef __ENABLE_MULTITHREADED_SUPPORT__
#define c_nvmem_write nvmem_write
#define c_nvmem_read nvmem_read
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */

//*****************************************************************************
//
//!  nvmem_read
//!
//!  @param  ulFileId   nvmem file id:\n
//!                     NVMEM_NVS_FILEID, NVMEM_NVS_SHADOW_FILEID,
//!                     NVMEM_WLAN_CONFIG_FILEID, NVMEM_WLAN_CONFIG_SHADOW_FILEID,
//!                     NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID,
//!                     NVMEM_MAC_FILEID, NVMEM_FRONTEND_VARS_FILEID,
//!                     NVMEM_IP_CONFIG_FILEID, NVMEM_IP_CONFIG_SHADOW_FILEID,
//!                     NVMEM_BOOTLOADER_SP_FILEID, NVMEM_RM_FILEID,
//!                     and user files 12-15.
//!  @param  ulLength    number of bytes to read
//!  @param  ulOffset    ulOffset in file from where to read
//!  @param  buff        output buffer pointer
//!
//!  @return       number of bytes read, otherwise error.
//!
//!  @brief       Reads data from the file referred by the ulFileId parameter.
//!               Reads data from file ulOffset till length. Err if the file can't
//!               be used, is invalid, or if the read is out of bounds.
//!
//*****************************************************************************
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
signed long c_nvmem_read(unsigned long ulFileId, unsigned long ulLength,
                                unsigned long ulOffset, unsigned char *buff)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
signed long nvmem_read(unsigned long ulFileId, unsigned long ulLength,
                                unsigned long ulOffset, unsigned char *buff)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    unsigned char ucStatus = 0xFF;
    unsigned char *ptr;
    unsigned char *args;

    ptr = tSLInformation.pucTxCommandBuffer;
    args = (ptr + HEADERS_SIZE_CMD);

    // Fill in HCI packet structure
    args = UINT32_TO_STREAM(args, ulFileId);
    args = UINT32_TO_STREAM(args, ulLength);
    args = UINT32_TO_STREAM(args, ulOffset);

    // Initiate a HCI command
    hci_command_send(HCI_CMND_NVMEM_READ, ptr, NVMEM_READ_PARAMS_LEN);
    SimpleLinkWaitEvent(HCI_CMND_NVMEM_READ, &ucStatus);

    // In case there is data - read it - even if an error code is returned
   // Note: It is the user responsibility to ignore the data in case of an error code

    // Wait for the data in a synchronous way. Here we assume that the buffer is
    // big enough to store also parameters of nvmem

    SimpleLinkWaitData(buff, 0, 0);

    return(ucStatus);
}

//*****************************************************************************
//
//!  nvmem_write
//!
//!  @param  ulFileId nvmem file id:\n
//!                   NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID,
//!                   NVMEM_MAC_FILEID, NVMEM_BOOTLOADER_SP_FILEID,
//!                   and user files 12-15.
//!  @param  ulLength       number of bytes to write
//!  @param  ulEntryOffset  offset in file to start write operation from
//!  @param  buff           data to write
//!
//!  @return       on success 0, error otherwise.
//!
//!  @brief       Write data to nvmem.
//!               writes data to file referred by the ulFileId parameter.
//!               Writes data to file ulOffset till ulLength.The file id will be
//!               marked invalid till the write is done. The file entry doesn't
//!               need to be valid - only allocated.
//!
//*****************************************************************************
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
signed long c_nvmem_write(unsigned long ulFileId, unsigned long ulLength, unsigned long ulEntryOffset, unsigned char *buff)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
signed long nvmem_write(unsigned long ulFileId, unsigned long ulLength, unsigned long ulEntryOffset, unsigned char *buff)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    long iRes;
    unsigned char *ptr;
    unsigned char *args;

    iRes = EFAIL;

    ptr = tSLInformation.pucTxCommandBuffer;
    args = (ptr + SPI_HEADER_SIZE + HCI_DATA_CMD_HEADER_SIZE);

    // Fill in HCI packet structure
    args = UINT32_TO_STREAM(args, ulFileId);
    args = UINT32_TO_STREAM(args, 12);
    args = UINT32_TO_STREAM(args, ulLength);
    args = UINT32_TO_STREAM(args, ulEntryOffset);

    memcpy((ptr + SPI_HEADER_SIZE + HCI_DATA_CMD_HEADER_SIZE +
                    NVMEM_WRITE_PARAMS_LEN),buff,ulLength);

    // Initiate a HCI command but it will come on data channel
    hci_data_command_send(HCI_CMND_NVMEM_WRITE, ptr, NVMEM_WRITE_PARAMS_LEN,
                                                ulLength);

    SimpleLinkWaitEvent(HCI_EVNT_NVMEM_WRITE, &iRes);

    return(iRes);
}


//*****************************************************************************
//
//!  nvmem_set_mac_address
//!
//!  @param  mac   mac address to be set
//!
//!  @return       on success 0, error otherwise.
//!
//!  @brief       Write MAC address to EEPROM.
//!               mac address as appears over the air (OUI first)
//!
//*****************************************************************************
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
unsigned char c_nvmem_set_mac_address(unsigned char *mac)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
unsigned char nvmem_set_mac_address(unsigned char *mac)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    return  c_nvmem_write(NVMEM_MAC_FILEID, MAC_ADDR_LEN, 0, mac);
}

//*****************************************************************************
//
//!  nvmem_get_mac_address
//!
//!  @param[out]  mac   mac address
//!
//!  @return       on success 0, error otherwise.
//!
//!  @brief       Read MAC address from EEPROM.
//!               mac address as appears over the air (OUI first)
//!
//*****************************************************************************
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
unsigned char c_nvmem_get_mac_address(unsigned char *mac)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
unsigned char nvmem_get_mac_address(unsigned char *mac)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    return  c_nvmem_read(NVMEM_MAC_FILEID, MAC_ADDR_LEN, 0, mac);
}
    /* init io callback */
    tSLInformation.ReadWlanInterruptPin = sReadWlanInterruptPin;
    tSLInformation.WlanInterruptEnable  = sWlanInterruptEnable;
    tSLInformation.WlanInterruptDisable = sWlanInterruptDisable;
    tSLInformation.WriteWlanPin = sWriteWlanPin;

    //init asynchronous events callback
    tSLInformation.sWlanCB= sWlanCB;

    // By default TX Complete events are routed to host too
    tSLInformation.InformHostOnTxComplete = 1;
}

//*****************************************************************************
//
//!  SpiReceiveHandler
//!
//!  @param         pvBuffer - pointer to the received data buffer
//!                      The function triggers Received event/data processing
//!
//!  @param         Pointer to the received data
//!  @return        none
//!
//!  @brief         The function triggers Received event/data processing. It is
//!                       called from the SPI library to receive the data
//
//*****************************************************************************
void SpiReceiveHandler(void *pvBuffer)
{
    tSLInformation.usEventOrDataReceived = 1;
    tSLInformation.pucReceivedData = (unsigned char     *)pvBuffer;

    hci_unsolicited_event_handler();
}


//*****************************************************************************
//
//!  wlan_start
//!
//!  @param   usPatchesAvailableAtHost -  flag to indicate if patches available
//!                                    from host or from EEPROM. Due to the
//!                                    fact the patches are burn to the EEPROM
//!                                    using the patch programmer utility, the
//!                                    patches will be available from the EEPROM
//!                                    and not from the host.
//!
//!  @return        none
//!
//!  @brief        Start WLAN device. This function asserts the enable pin of
//!                the device (WLAN_EN), starting the HW initialization process.
//!                The function blocked until device Initialization is completed.
//!                Function also configure patches (FW, driver or bootloader)
//!                and calls appropriate device callbacks.
//!
//!  @Note          Prior calling the function wlan_init shall be called.
//!  @Warning       This function must be called after wlan_init and before any
//!                 other wlan API
//!  @sa            wlan_init , wlan_stop
//!
//
//*****************************************************************************

#ifdef __ENABLE_MULTITHREADED_SUPPORT__
void c_wlan_start(unsigned short usPatchesAvailableAtHost)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
void wlan_start(unsigned short usPatchesAvailableAtHost)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{

    unsigned long ulSpiIRQState;

    tSLInformation.NumberOfSentPackets = 0;
    tSLInformation.NumberOfReleasedPackets = 0;
    tSLInformation.usRxEventOpcode = 0;
    tSLInformation.usNumberOfFreeBuffers = 0;
    tSLInformation.usSlBufferLength = 0;
    tSLInformation.usBufferSize = 0;
    tSLInformation.usRxDataPending = 0;
    tSLInformation.slTransmitDataError = 0;
    tSLInformation.usEventOrDataReceived = 0;
    tSLInformation.pucReceivedData = 0;

    // Allocate the memory for the RX/TX data transactions
    tSLInformation.pucTxCommandBuffer = (unsigned char *)wlan_tx_buffer;

    // init spi
    SpiOpen(SpiReceiveHandler);

    // Check the IRQ line
    ulSpiIRQState = tSLInformation.ReadWlanInterruptPin();

    // ASIC 1273 chip enable: toggle WLAN EN line
    tSLInformation.WriteWlanPin( WLAN_ENABLE );

    if (ulSpiIRQState)
    {
        // wait till the IRQ line goes low
        while(tSLInformation.ReadWlanInterruptPin() != 0)
        {
        }
    }
    else
    {
        // Wait till the IRQ line goes high and then low.
        while(tSLInformation.ReadWlanInterruptPin() == 0)
        {
        }

        while(tSLInformation.ReadWlanInterruptPin() != 0)
        {
        }
    }

    SimpleLink_Init_Start(usPatchesAvailableAtHost);

    // Read Buffer's size and finish
    hci_command_send(HCI_CMND_READ_BUFFER_SIZE, tSLInformation.pucTxCommandBuffer, 0);
    SimpleLinkWaitEvent(HCI_CMND_READ_BUFFER_SIZE, 0);
}


//*****************************************************************************
//
//!  wlan_stop
//!
//!  @param         none
//!
//!  @return        none
//!
//!  @brief         Stop WLAN device by putting it into reset state.
//!
//!  @sa            wlan_start
//
//*****************************************************************************
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
void c_wlan_stop(void)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
void wlan_stop(void)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    // ASIC 1273 chip disable
    tSLInformation.WriteWlanPin( WLAN_DISABLE );

    // Wait till IRQ line goes high...
    while(tSLInformation.ReadWlanInterruptPin() == 0)
    {
    }

    // Free the used by WLAN Driver memory
    if (tSLInformation.pucTxCommandBuffer)
    {
        tSLInformation.pucTxCommandBuffer = 0;
    }

    SpiClose();
}


//*****************************************************************************
//
//!  wlan_connect
//!
//!  @param    sec_type   security options:
//!               WLAN_SEC_UNSEC,
//!               WLAN_SEC_WEP (ASCII support only),
//!               WLAN_SEC_WPA or WLAN_SEC_WPA2
//!  @param    ssid       up to 32 bytes and is ASCII SSID of the AP
//!  @param    ssid_len   length of the SSID
//!  @param    bssid      6 bytes specified the AP bssid
//!  @param    key        up to 16 bytes specified the AP security key
//!  @param    key_len    key length
//!
//!  @return     On success, zero is returned. On error, negative is returned.
//!              Note that even though a zero is returned on success to trigger
//!              connection operation, it does not mean that CCC3000 is already
//!              connected. An asynchronous "Connected" event is generated when
//!              actual association process finishes and CC3000 is connected to
//!              the AP. If DHCP is set, An asynchronous "DHCP" event is
//!              generated when DHCP process is finish.
//!
//!
//!  @brief      Connect to AP
//!  @warning    Please Note that when connection to AP configured with security
//!              type WEP, please confirm that the key is set as ASCII and not
//!              as HEX.
//!  @sa         wlan_disconnect
//
//*****************************************************************************

#ifndef CC3000_TINY_DRIVER
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
long c_wlan_connect(unsigned long ulSecType, char *ssid, long ssid_len,
                    unsigned char *bssid, unsigned char *key, long key_len)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
long wlan_connect(unsigned long ulSecType, char *ssid, long ssid_len,
                  unsigned char *bssid, unsigned char *key, long key_len)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    long ret;
    unsigned char *ptr;
    unsigned char *args;
    unsigned char bssid_zero[] = {0, 0, 0, 0, 0, 0};

    ret     = EFAIL;
    ptr     = tSLInformation.pucTxCommandBuffer;
    args    = (ptr + HEADERS_SIZE_CMD);

    // Fill in command buffer
    args = UINT32_TO_STREAM(args, 0x0000001c);
    args = UINT32_TO_STREAM(args, ssid_len);
    args = UINT32_TO_STREAM(args, ulSecType);
    args = UINT32_TO_STREAM(args, 0x00000010 + ssid_len);
    args = UINT32_TO_STREAM(args, key_len);
    args = UINT16_TO_STREAM(args, 0);

    // padding shall be zeroed
    if(bssid)
    {
        ARRAY_TO_STREAM(args, bssid, ETH_ALEN);
    }
    else
    {
        ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN);
    }

    ARRAY_TO_STREAM(args, ssid, ssid_len);

    if(key_len && key)
    {
        ARRAY_TO_STREAM(args, key, key_len);
    }

    // Initiate a HCI command
    hci_command_send(HCI_CMND_WLAN_CONNECT, ptr, WLAN_CONNECT_PARAM_LEN +
                                     ssid_len + key_len - 1);

    // Wait for command complete event
    SimpleLinkWaitEvent(HCI_CMND_WLAN_CONNECT, &ret);
    errno = ret;

    return(ret);
}
#else
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
long c_wlan_connect(char *ssid, long ssid_len)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
long wlan_connect(char *ssid, long ssid_len)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    long ret;
    unsigned char *ptr;
    unsigned char *args;
    unsigned char bssid_zero[] = {0, 0, 0, 0, 0, 0};

    ret     = EFAIL;
    ptr     = tSLInformation.pucTxCommandBuffer;
    args    = (ptr + HEADERS_SIZE_CMD);

    // Fill in command buffer
    args = UINT32_TO_STREAM(args, 0x0000001c);
    args = UINT32_TO_STREAM(args, ssid_len);
    args = UINT32_TO_STREAM(args, 0);
    args = UINT32_TO_STREAM(args, 0x00000010 + ssid_len);
    args = UINT32_TO_STREAM(args, 0);
    args = UINT16_TO_STREAM(args, 0);

    // padding shall be zeroed
    ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN);
    ARRAY_TO_STREAM(args, ssid, ssid_len);

    // Initiate a HCI command
    hci_command_send(HCI_CMND_WLAN_CONNECT, ptr, WLAN_CONNECT_PARAM_LEN +
                                     ssid_len  - 1);

    // Wait for command complete event
    SimpleLinkWaitEvent(HCI_CMND_WLAN_CONNECT, &ret);
    errno = ret;

    return(ret);
}
#endif

//*****************************************************************************
//
//!  wlan_disconnect
//!
//!  @return    0 disconnected done, other CC3000 already disconnected
//!
//!  @brief      Disconnect connection from AP.
//!
//!  @sa         wlan_connect
//
//*****************************************************************************
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
long c_wlan_disconnect(void)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
long wlan_disconnect(void)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    long ret;
    unsigned char *ptr;

    ret = EFAIL;
    ptr = tSLInformation.pucTxCommandBuffer;

    hci_command_send(HCI_CMND_WLAN_DISCONNECT, ptr, 0);

    // Wait for command complete event
    SimpleLinkWaitEvent(HCI_CMND_WLAN_DISCONNECT, &ret);
    errno = ret;

    return(ret);
}

//*****************************************************************************
//
//!  wlan_ioctl_set_connection_policy
//!
//!  @param    should_connect_to_open_ap  enable(1), disable(0) connect to any
//!            available AP. This parameter corresponds to the configuration of
//!            item # 3 in the brief description.
//!  @param    should_use_fast_connect enable(1), disable(0). if enabled, tries
//!            to connect to the last connected AP. This parameter corresponds
//!            to the configuration of item # 1 in the brief description.
//!  @param    auto_start enable(1), disable(0) auto connect
//!            after reset and periodically reconnect if needed. This
//!            configuration configures option 2 in the above description.
//!
//!  @return     On success, zero is returned. On error, -1 is returned
//!
//!  @brief      When auto is enabled, the device tries to connect according
//!              the following policy:
//!              1) If fast connect is enabled and last connection is valid,
//!                 the device will try to connect to it without the scanning
//!                 procedure (fast). The last connection will be marked as
//!                 invalid, due to adding/removing profile.
//!              2) If profile exists, the device will try to connect it
//!                 (Up to seven profiles).
//!              3) If fast and profiles are not found, and open mode is
//!                 enabled, the device will try to connect to any AP.
//!              * Note that the policy settings are stored in the CC3000 NVMEM.
//!
//!  @sa         wlan_add_profile , wlan_ioctl_del_profile
//
//*****************************************************************************
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
long c_wlan_ioctl_set_connection_policy(unsigned long should_connect_to_open_ap,
                                        unsigned long ulShouldUseFastConnect,
                                        unsigned long ulUseProfiles)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
long wlan_ioctl_set_connection_policy(unsigned long should_connect_to_open_ap,
                                        unsigned long ulShouldUseFastConnect,
                                        unsigned long ulUseProfiles)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    long ret;
    unsigned char *ptr;
    unsigned char *args;

    ret = EFAIL;
    ptr = tSLInformation.pucTxCommandBuffer;
    args = (unsigned char *)(ptr + HEADERS_SIZE_CMD);

    // Fill in HCI packet structure
    args = UINT32_TO_STREAM(args, should_connect_to_open_ap);
    args = UINT32_TO_STREAM(args, ulShouldUseFastConnect);
    args = UINT32_TO_STREAM(args, ulUseProfiles);

    // Initiate a HCI command
    hci_command_send(HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY,
                    ptr, WLAN_SET_CONNECTION_POLICY_PARAMS_LEN);

    // Wait for command complete event
    SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY, &ret);

    return(ret);
}

//*****************************************************************************
//
//!  wlan_add_profile
//!
//!  @param    ulSecType  WLAN_SEC_UNSEC,WLAN_SEC_WEP,WLAN_SEC_WPA,WLAN_SEC_WPA2
//!  @param    ucSsid    ssid  SSID up to 32 bytes
//!  @param    ulSsidLen ssid length
//!  @param    ucBssid   bssid  6 bytes
//!  @param    ulPriority ulPriority profile priority. Lowest priority:0.
//!			   Important Note: Smartconfig process (in unencrypted mode)
//!			   stores the profile internally with priority 1, so changing
//!			   priorities when adding new profiles should be done with extra care
//!  @param    ulPairwiseCipher_Or_TxKeyLen  key length for WEP security
//!  @param    ulGroupCipher_TxKeyIndex  key index
//!  @param    ulKeyMgmt        KEY management
//!  @param    ucPf_OrKey       security key
//!  @param    ulPassPhraseLen  security key length for WPA\WPA2
//!
//!  @return    On success, index (1-7) of the stored profile is returned.
//!				On error, -1 is returned.
//!
//!  @brief     When auto start is enabled, the device connects to
//!             station from the profiles table. Up to 7 profiles are supported.
//!             If several profiles configured the device choose the highest
//!             priority profile, within each priority group, device will choose
//!             profile based on security policy, signal strength, etc
//!             parameters. All the profiles are stored in CC3000 NVMEM.
//!
//!  @sa        wlan_ioctl_del_profile
//
//*****************************************************************************

#ifndef CC3000_TINY_DRIVER
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
long c_wlan_add_profile(unsigned long ulSecType,
                                        unsigned char* ucSsid,
                                        unsigned long ulSsidLen,
                                        unsigned char *ucBssid,
                                        unsigned long ulPriority,
                                        unsigned long ulPairwiseCipher_Or_TxKeyLen,
                                        unsigned long ulGroupCipher_TxKeyIndex,
                                        unsigned long ulKeyMgmt,
                                        unsigned char* ucPf_OrKey,
                                        unsigned long ulPassPhraseLen)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
long wlan_add_profile(unsigned long ulSecType,
                                        unsigned char* ucSsid,
                                        unsigned long ulSsidLen,
                                        unsigned char *ucBssid,
                                        unsigned long ulPriority,
                                        unsigned long ulPairwiseCipher_Or_TxKeyLen,
                                        unsigned long ulGroupCipher_TxKeyIndex,
                                        unsigned long ulKeyMgmt,
                                        unsigned char* ucPf_OrKey,
                                        unsigned long ulPassPhraseLen)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    unsigned short arg_len;
    long ret;
    unsigned char *ptr;
    long i = 0;
    unsigned char *args;
    unsigned char bssid_zero[] = {0, 0, 0, 0, 0, 0};

    ptr = tSLInformation.pucTxCommandBuffer;
    args = (ptr + HEADERS_SIZE_CMD);

    args = UINT32_TO_STREAM(args, ulSecType);

    // Setup arguments in accordance with the security type
    switch (ulSecType)
    {
        //OPEN
        case WLAN_SEC_UNSEC:
        {
            args = UINT32_TO_STREAM(args, 0x00000014);
            args = UINT32_TO_STREAM(args, ulSsidLen);
            args = UINT16_TO_STREAM(args, 0);
            if(ucBssid)
            {
                ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN);
            }
            else
            {
                ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN);
            }
            args = UINT32_TO_STREAM(args, ulPriority);
            ARRAY_TO_STREAM(args, ucSsid, ulSsidLen);

            arg_len = WLAN_ADD_PROFILE_NOSEC_PARAM_LEN + ulSsidLen;
        }
        break;

        //WEP
        case WLAN_SEC_WEP:
        {
            args = UINT32_TO_STREAM(args, 0x00000020);
            args = UINT32_TO_STREAM(args, ulSsidLen);
            args = UINT16_TO_STREAM(args, 0);
            if(ucBssid)
            {
                ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN);
            }
            else
            {
                ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN);
            }
            args = UINT32_TO_STREAM(args, ulPriority);
            args = UINT32_TO_STREAM(args, 0x0000000C + ulSsidLen);
            args = UINT32_TO_STREAM(args, ulPairwiseCipher_Or_TxKeyLen);
            args = UINT32_TO_STREAM(args, ulGroupCipher_TxKeyIndex);
            ARRAY_TO_STREAM(args, ucSsid, ulSsidLen);

            for(i = 0; i < 4; i++)
            {
                unsigned char *p = &ucPf_OrKey[i * ulPairwiseCipher_Or_TxKeyLen];

                ARRAY_TO_STREAM(args, p, ulPairwiseCipher_Or_TxKeyLen);
            }

            arg_len = WLAN_ADD_PROFILE_WEP_PARAM_LEN + ulSsidLen +
                ulPairwiseCipher_Or_TxKeyLen * 4;

        }
        break;

        //WPA
        //WPA2
        case WLAN_SEC_WPA:
        case WLAN_SEC_WPA2:
        {
            args = UINT32_TO_STREAM(args, 0x00000028);
            args = UINT32_TO_STREAM(args, ulSsidLen);
            args = UINT16_TO_STREAM(args, 0);
            if(ucBssid)
            {
                ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN);
            }
            else
            {
                ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN);
            }
            args = UINT32_TO_STREAM(args, ulPriority);
            args = UINT32_TO_STREAM(args, ulPairwiseCipher_Or_TxKeyLen);
            args = UINT32_TO_STREAM(args, ulGroupCipher_TxKeyIndex);
            args = UINT32_TO_STREAM(args, ulKeyMgmt);
            args = UINT32_TO_STREAM(args, 0x00000008 + ulSsidLen);
            args = UINT32_TO_STREAM(args, ulPassPhraseLen);
            ARRAY_TO_STREAM(args, ucSsid, ulSsidLen);
            ARRAY_TO_STREAM(args, ucPf_OrKey, ulPassPhraseLen);

            arg_len = WLAN_ADD_PROFILE_WPA_PARAM_LEN + ulSsidLen + ulPassPhraseLen;
        }

        break;

        //
        // An unrecognized security type was detected. Return an error.
        //
        default:
        {
            return(-1);
        }
    }

    // Initiate a HCI command
    hci_command_send(HCI_CMND_WLAN_IOCTL_ADD_PROFILE,
        ptr, arg_len);

    // Wait for command complete event
    SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_ADD_PROFILE, &ret);

    return(ret);
}
#else
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
long c_wlan_add_profile(unsigned long ulSecType,
                                        unsigned char* ucSsid,
                                        unsigned long ulSsidLen,
                                        unsigned char *ucBssid,
                                        unsigned long ulPriority,
                                        unsigned long ulPairwiseCipher_Or_TxKeyLen,
                                        unsigned long ulGroupCipher_TxKeyIndex,
                                        unsigned long ulKeyMgmt,
                                        unsigned char* ucPf_OrKey,
                                        unsigned long ulPassPhraseLen)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
long wlan_add_profile(unsigned long ulSecType,
                                        unsigned char* ucSsid,
                                        unsigned long ulSsidLen,
                                        unsigned char *ucBssid,
                                        unsigned long ulPriority,
                                        unsigned long ulPairwiseCipher_Or_TxKeyLen,
                                        unsigned long ulGroupCipher_TxKeyIndex,
                                        unsigned long ulKeyMgmt,
                                        unsigned char* ucPf_OrKey,
                                        unsigned long ulPassPhraseLen)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    return -1;
}
#endif

//*****************************************************************************
//
//!  wlan_ioctl_del_profile
//!
//!  @param    index   number of profile to delete
//!
//!  @return    On success, zero is returned. On error, -1 is returned
//!
//!  @brief     Delete WLAN profile
//!
//!  @Note      In order to delete all stored profile, set index to 255.
//!
//!  @sa        wlan_add_profile
//
//*****************************************************************************
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
long c_wlan_ioctl_del_profile(unsigned long ulIndex)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
long wlan_ioctl_del_profile(unsigned long ulIndex)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    long ret;
    unsigned char *ptr;
    unsigned char *args;

    ptr = tSLInformation.pucTxCommandBuffer;
    args = (unsigned char *)(ptr + HEADERS_SIZE_CMD);

    // Fill in HCI packet structure
    args = UINT32_TO_STREAM(args, ulIndex);
    ret = EFAIL;

    // Initiate a HCI command
    hci_command_send(HCI_CMND_WLAN_IOCTL_DEL_PROFILE,
        ptr, WLAN_DEL_PROFILE_PARAMS_LEN);

    // Wait for command complete event
    SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_DEL_PROFILE, &ret);

    return(ret);
}

//*****************************************************************************
//
//!  wlan_ioctl_get_scan_results
//!
//!  @param[in]    scan_timeout   parameter not supported
//!  @param[out]   ucResults  scan results (_wlan_full_scan_results_args_t)
//!
//!  @return    On success, zero is returned. On error, -1 is returned
//!
//!  @brief    Gets entry from scan result table.
//!            The scan results are returned one by one, and each entry
//!            represents a single AP found in the area. The following is a
//!            format of the scan result:
//!          - 4 Bytes: number of networks found
//!          - 4 Bytes: The status of the scan: 0 - aged results,
//!                     1 - results valid, 2 - no results
//!          - 42 bytes: Result entry, where the bytes are arranged as  follows:
//!
//!                         - 1 bit isValid - is result valid or not
//!                         - 7 bits rssi - RSSI value;
//!                 - 2 bits: securityMode - security mode of the AP:
//!                           0 - Open, 1 - WEP, 2 WPA, 3 WPA2
//!                         - 6 bits: SSID name length
//!                         - 2 bytes: the time at which the entry has entered into
//!                            scans result table
//!                         - 32 bytes: SSID name
//!                 - 6 bytes:  BSSID
//!
//!  @Note      scan_timeout, is not supported on this version.
//!
//!  @sa        wlan_ioctl_set_scan_params
//
//*****************************************************************************
#ifndef CC3000_TINY_DRIVER
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
long c_wlan_ioctl_get_scan_results(unsigned long ulScanTimeout,
                                   unsigned char *ucResults)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
long wlan_ioctl_get_scan_results(unsigned long ulScanTimeout,
                                   unsigned char *ucResults)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    unsigned char *ptr;
    unsigned char *args;

    ptr = tSLInformation.pucTxCommandBuffer;
    args = (ptr + HEADERS_SIZE_CMD);

    // Fill in temporary command buffer
    args = UINT32_TO_STREAM(args, ulScanTimeout);

    // Initiate a HCI command
    hci_command_send(HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS,
        ptr, WLAN_GET_SCAN_RESULTS_PARAMS_LEN);

    // Wait for command complete event
    SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS, ucResults);

    return(0);
}
#endif

//*****************************************************************************
//
//!  wlan_ioctl_set_scan_params
//!
//!  @param    uiEnable - start/stop application scan:
//!            1 = start scan with default interval value of 10 min.
//!            in order to set a different scan interval value apply the value
//!            in milliseconds. minimum 1 second. 0=stop). Wlan reset
//!           (wlan_stop() wlan_start()) is needed when changing scan interval
//!            value. Saved: No
//!  @param   uiMinDwellTime   minimum dwell time value to be used for each
//!           channel, in milliseconds. Saved: yes
//!           Recommended Value: 100 (Default: 20)
//!  @param   uiMaxDwellTime    maximum dwell time value to be used for each
//!           channel, in milliseconds. Saved: yes
//!           Recommended Value: 100 (Default: 30)
//!  @param   uiNumOfProbeRequests  max probe request between dwell time.
//!           Saved: yes. Recommended Value: 5 (Default:2)
//!  @param   uiChannelMask  bitwise, up to 13 channels (0x1fff).
//!           Saved: yes. Default: 0x7ff
//!  @param   uiRSSIThreshold   RSSI threshold. Saved: yes (Default: -80)
//!  @param   uiSNRThreshold    NSR threshold. Saved: yes (Default: 0)
//!  @param   uiDefaultTxPower  probe Tx power. Saved: yes (Default: 205)
//!  @param   aiIntervalList    pointer to array with 16 entries (16 channels)
//!           each entry (unsigned long) holds timeout between periodic scan
//!           (connection scan) - in millisecond. Saved: yes. Default 2000ms.
//!
//!  @return    On success, zero is returned. On error, -1 is returned
//!
//!  @brief    start and stop scan procedure. Set scan parameters.
//!
//!  @Note     uiDefaultTxPower, is not supported on this version.
//!
//!  @sa        wlan_ioctl_get_scan_results
//
//*****************************************************************************
#ifndef CC3000_TINY_DRIVER
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
long c_wlan_ioctl_set_scan_params(unsigned long uiEnable, unsigned long uiMinDwellTime,
                                  unsigned long uiMaxDwellTime, unsigned long uiNumOfProbeRequests,
                                  unsigned long uiChannelMask, long iRSSIThreshold,
                                  unsigned long uiSNRThreshold, unsigned long uiDefaultTxPower,
                                  unsigned long *aiIntervalList)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
long wlan_ioctl_set_scan_params(unsigned long uiEnable, unsigned long uiMinDwellTime,
                                  unsigned long uiMaxDwellTime, unsigned long uiNumOfProbeRequests,
                                  unsigned long uiChannelMask, long iRSSIThreshold,
                                  unsigned long uiSNRThreshold, unsigned long uiDefaultTxPower,
                                  unsigned long *aiIntervalList)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    unsigned long  uiRes;
    unsigned char *ptr;
    unsigned char *args;

    ptr = tSLInformation.pucTxCommandBuffer;
    args = (ptr + HEADERS_SIZE_CMD);

    // Fill in temporary command buffer
    args = UINT32_TO_STREAM(args, 36);
    args = UINT32_TO_STREAM(args, uiEnable);
    args = UINT32_TO_STREAM(args, uiMinDwellTime);
    args = UINT32_TO_STREAM(args, uiMaxDwellTime);
    args = UINT32_TO_STREAM(args, uiNumOfProbeRequests);
    args = UINT32_TO_STREAM(args, uiChannelMask);
    args = UINT32_TO_STREAM(args, iRSSIThreshold);
    args = UINT32_TO_STREAM(args, uiSNRThreshold);
    args = UINT32_TO_STREAM(args, uiDefaultTxPower);
    ARRAY_TO_STREAM(args, aiIntervalList, sizeof(unsigned long) *
                                    SL_SET_SCAN_PARAMS_INTERVAL_LIST_SIZE);

    // Initiate a HCI command
    hci_command_send(HCI_CMND_WLAN_IOCTL_SET_SCANPARAM,
        ptr, WLAN_SET_SCAN_PARAMS_LEN);

    // Wait for command complete event
    SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SET_SCANPARAM, &uiRes);

    return(uiRes);
}
#endif

//*****************************************************************************
//
//!  wlan_set_event_mask
//!
//!  @param    mask   mask option:
//!       HCI_EVNT_WLAN_UNSOL_CONNECT connect event
//!       HCI_EVNT_WLAN_UNSOL_DISCONNECT disconnect event
//!       HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE  smart config done
//!       HCI_EVNT_WLAN_UNSOL_INIT init done
//!       HCI_EVNT_WLAN_UNSOL_DHCP dhcp event report
//!       HCI_EVNT_WLAN_ASYNC_PING_REPORT ping report
//!       HCI_EVNT_WLAN_KEEPALIVE keepalive
//!       HCI_EVNT_WLAN_TX_COMPLETE - disable information on end of transmission
//!       Saved: no.
//!
//!  @return    On success, zero is returned. On error, -1 is returned
//!
//!  @brief    Mask event according to bit mask. In case that event is
//!            masked (1), the device will not send the masked event to host.
//
//*****************************************************************************
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
long c_wlan_set_event_mask(unsigned long ulMask)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
long wlan_set_event_mask(unsigned long ulMask)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    long ret;
    unsigned char *ptr;
    unsigned char *args;


    if ((ulMask & HCI_EVNT_WLAN_TX_COMPLETE) == HCI_EVNT_WLAN_TX_COMPLETE)
    {
        tSLInformation.InformHostOnTxComplete = 0;

        // Since an event is a virtual event - i.e. it is not coming from CC3000
        // there is no need to send anything to the device if it was an only event
        if (ulMask == HCI_EVNT_WLAN_TX_COMPLETE)
        {
            return 0;
        }

        ulMask &= ~HCI_EVNT_WLAN_TX_COMPLETE;
        ulMask |= HCI_EVNT_WLAN_UNSOL_BASE;
    }
    else
    {
        tSLInformation.InformHostOnTxComplete = 1;
    }

    ret = EFAIL;
    ptr = tSLInformation.pucTxCommandBuffer;
    args = (unsigned char *)(ptr + HEADERS_SIZE_CMD);

    // Fill in HCI packet structure
    args = UINT32_TO_STREAM(args, ulMask);

    // Initiate a HCI command
    hci_command_send(HCI_CMND_EVENT_MASK,
        ptr, WLAN_SET_MASK_PARAMS_LEN);

    // Wait for command complete event
    SimpleLinkWaitEvent(HCI_CMND_EVENT_MASK, &ret);

    return(ret);
}

//*****************************************************************************
//
//!  wlan_ioctl_statusget
//!
//!  @param none
//!
//!  @return    WLAN_STATUS_DISCONNECTED, WLAN_STATUS_SCANING,
//!             STATUS_CONNECTING or WLAN_STATUS_CONNECTED
//!
//!  @brief    get wlan status: disconnected, scanning, connecting or connected
//
//*****************************************************************************
#ifndef CC3000_TINY_DRIVER
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
long c_wlan_ioctl_statusget(void)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
long wlan_ioctl_statusget(void)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    long ret;
    unsigned char *ptr;

    ret = EFAIL;
    ptr = tSLInformation.pucTxCommandBuffer;

    hci_command_send(HCI_CMND_WLAN_IOCTL_STATUSGET,
        ptr, 0);

    // Wait for command complete event
    SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_STATUSGET, &ret);

    return(ret);
}
#endif

//*****************************************************************************
//
//!  wlan_smart_config_start
//!
//!  @param    algoEncryptedFlag indicates whether the information is encrypted
//!
//!  @return   On success, zero is returned. On error, -1 is returned
//!
//!  @brief   Start to acquire device profile. The device acquire its own
//!           profile, if profile message is found. The acquired AP information
//!           is stored in CC3000 EEPROM only in case AES128 encryption is used.
//!           In case AES128 encryption is not used, a profile is created by
//!           CC3000 internally.
//!
//!  @Note    An asynchronous event - Smart Config Done will be generated as soon
//!           as the process finishes successfully.
//!
//!  @sa      wlan_smart_config_set_prefix , wlan_smart_config_stop
//
//*****************************************************************************
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
long c_wlan_smart_config_start(unsigned long algoEncryptedFlag)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
long wlan_smart_config_start(unsigned long algoEncryptedFlag)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    long ret;
    unsigned char *ptr;
    unsigned char *args;

    ret = EFAIL;
    ptr = tSLInformation.pucTxCommandBuffer;
    args = (unsigned char *)(ptr + HEADERS_SIZE_CMD);

    // Fill in HCI packet structure
    args = UINT32_TO_STREAM(args, algoEncryptedFlag);
    ret = EFAIL;

    hci_command_send(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START, ptr,
                                     WLAN_SMART_CONFIG_START_PARAMS_LEN);

    // Wait for command complete event
    SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START, &ret);

    return(ret);
}

//*****************************************************************************
//
//!  wlan_smart_config_stop
//!
//!  @param    algoEncryptedFlag indicates whether the information is encrypted
//!
//!  @return   On success, zero is returned. On error, -1 is returned
//!
//!  @brief   Stop the acquire profile procedure
//!
//!  @sa      wlan_smart_config_start , wlan_smart_config_set_prefix
//
//*****************************************************************************
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
long c_wlan_smart_config_stop(void)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
long wlan_smart_config_stop(void)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    long ret;
    unsigned char *ptr;

    ret = EFAIL;
    ptr = tSLInformation.pucTxCommandBuffer;

    hci_command_send(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP, ptr, 0);

    // Wait for command complete event
    SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP, &ret);

    return(ret);
}

//*****************************************************************************
//
//!  wlan_smart_config_set_prefix
//!
//!  @param   newPrefix  3 bytes identify the SSID prefix for the Smart Config.
//!
//!  @return   On success, zero is returned. On error, -1 is returned
//!
//!  @brief   Configure station ssid prefix. The prefix is used internally
//!           in CC3000. It should always be TTT.
//!
//!  @Note    The prefix is stored in CC3000 NVMEM
//!
//!  @sa      wlan_smart_config_start , wlan_smart_config_stop
//
//*****************************************************************************
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
long c_wlan_smart_config_set_prefix(char* cNewPrefix)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
long wlan_smart_config_set_prefix(char* cNewPrefix)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    long ret;
    unsigned char *ptr;
    unsigned char *args;

    ret = EFAIL;
    ptr = tSLInformation.pucTxCommandBuffer;
    args = (ptr + HEADERS_SIZE_CMD);

    if (cNewPrefix == NULL)
        return ret;
    else    // with the new Smart Config, prefix must be TTT
    {
        *cNewPrefix = 'T';
        *(cNewPrefix + 1) = 'T';
        *(cNewPrefix + 2) = 'T';
    }

    ARRAY_TO_STREAM(args, cNewPrefix, SL_SIMPLE_CONFIG_PREFIX_LENGTH);

    hci_command_send(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX, ptr,
                                     SL_SIMPLE_CONFIG_PREFIX_LENGTH);

    // Wait for command complete event
    SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX, &ret);

    return(ret);
}

//*****************************************************************************
//
//!  wlan_smart_config_process
//!
//!  @param   none
//!
//!  @return   On success, zero is returned. On error, -1 is returned
//!
//!  @brief   process the acquired data and store it as a profile. The acquired
//!           AP information is stored in CC3000 EEPROM encrypted.
//!           The encrypted data is decrypted and stored as a profile.
//!           behavior is as defined by connection policy.
//
//*****************************************************************************
#ifndef __ENABLE_MULTITHREADED_SUPPORT__
#define c_wlan_add_profile wlan_add_profile
#define c_aes_read_key aes_read_key
#define c_nvmem_read nvmem_read
#define c_aes_decrypt aes_decrypt
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */

#ifndef CC3000_UNENCRYPTED_SMART_CONFIG
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
long c_wlan_smart_config_process()
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
long wlan_smart_config_process()
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    signed long returnValue;
    unsigned long ssidLen, keyLen;
    unsigned char *decKeyPtr;
    unsigned char *ssidPtr;

    // read the key from EEPROM - fileID 12
    returnValue = c_aes_read_key(key);

     if (returnValue != 0)
        return returnValue;

    // read the received data from fileID #13 and parse it according to the followings:
    // 1) SSID LEN - not encrypted
    // 2) SSID - not encrypted
    // 3) KEY LEN - not encrypted. always 32 bytes long
    // 4) Security type - not encrypted
    // 5) KEY - encrypted together with true key length as the first byte in KEY
    //   to elaborate, there are two corner cases:
    //      1) the KEY is 32 bytes long. In this case, the first byte does not represent KEY length
    //      2) the KEY is 31 bytes long. In this case, the first byte represent KEY length and equals 31
    returnValue = c_nvmem_read(NVMEM_SHARED_MEM_FILEID, SMART_CONFIG_PROFILE_SIZE, 0, profileArray);
    if (returnValue != 0)
        return returnValue;

    ssidPtr = &profileArray[1];

    ssidLen = profileArray[0];

    decKeyPtr = &profileArray[profileArray[0] + 3];

    c_aes_decrypt(decKeyPtr, key);
    if (profileArray[profileArray[0] + 1] > 16)
        c_aes_decrypt((unsigned char *)(decKeyPtr + 16), key);

    if (*(unsigned char *)(decKeyPtr +31) != 0)
    {
        if (*decKeyPtr == 31)
        {
            keyLen = 31;
            decKeyPtr++;
        }
        else
        {
            keyLen = 32;
        }
    }
    else
    {
        keyLen = *decKeyPtr;
        decKeyPtr++;
    }

    // add a profile
     switch (profileArray[profileArray[0] + 2])
     {
        case WLAN_SEC_UNSEC://None
        {
            returnValue = c_wlan_add_profile(profileArray[profileArray[0] + 2],     // security type
                                             ssidPtr,                               // SSID
                                             ssidLen,                               // SSID length
                                             NULL,                                  // BSSID
                                             1,                                     // Priority
                                             0, 0, 0, 0, 0);

            break;
        }

        case WLAN_SEC_WEP://WEP
        {
            returnValue = c_wlan_add_profile(profileArray[profileArray[0] + 2],     // security type
                                             ssidPtr,                               // SSID
                                             ssidLen,                               // SSID length
                                             NULL,                                  // BSSID
                                             1,                                     // Priority
                                             keyLen,                                // KEY length
                                             0,                                     // KEY index
                                             0,
                                             decKeyPtr,                             // KEY
                                             0);

            break;
        }

        case WLAN_SEC_WPA://WPA
              case WLAN_SEC_WPA2://WPA2
              {
                returnValue = c_wlan_add_profile(profileArray[profileArray[0] + 2],     // security type
                                                 ssidPtr,
                                                 ssidLen,
                                                 NULL,                                  // BSSID
                                                 1,                                     // Priority
                                                 0x18,                                  // PairwiseCipher
                                                 0x1e,                                  // GroupCipher
                                                 2,                                     // KEY management
                                                 decKeyPtr,                             // KEY
                                                 keyLen);                               // KEY length

            break;
        }
     }

     return returnValue;
}