Port of TI's CC3100 Websock camera demo. Using FreeRTOS, mbedTLS, also parts of Arducam for cams ov5642 and 0v2640. Can also use MT9D111. Work in progress. Be warned some parts maybe a bit flacky. This is for Seeed Arch max only, for an M3, see the demo for CM3 using the 0v5642 aducam mini.

Dependencies:   mbed

simplelink/cc3100.cpp

Committer:
dflet
Date:
2015-09-15
Revision:
22:f9b5e0b80bf2
Parent:
19:3dd3e7f30f8b

File content as of revision 22:f9b5e0b80bf2:

/*
* device.c - CC31xx/CC32xx Host Driver Implementation
*
* Copyright (C) 2014 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.
*
*/



/*****************************************************************************/
/* Include files                                                             */
/*****************************************************************************/
#include "cc3100_simplelink.h"
#include "cc3100_protocol.h"
#include "cc3100_sl_common.h"
#include "cc3100.h"

#include "fPtr_func.h"
#include "cli_uart.h"
#include "osi.h"
#include "Led_config.h"

namespace mbed_cc3100 {	

    uint32_t  g_PingPacketsRecv;
    uint32_t  g_GatewayIP;
    uint32_t  g_StationIP;
    uint32_t  g_DestinationIP;
    uint32_t  g_BytesReceived; // variable to store the file size 
    uint32_t  g_Status;
    uint8_t   g_buff[MAX_BUFF_SIZE+1];
    int32_t   g_SockID;
		

//#ifndef SL_PLATFORM_MULTI_THREADED
#if (!defined (SL_PLATFORM_MULTI_THREADED)) && (!defined (SL_PLATFORM_EXTERNAL_SPAWN))
cc3100::cc3100(PinName button1_irq, PinName button2_irq, PinName cc3100_irq, PinName cc3100_nHIB, PinName cc3100_cs, SPI cc3100_spi)
    : _spi(button1_irq, button2_irq, cc3100_irq, cc3100_nHIB, cc3100_cs, cc3100_spi, _driver),
      _driver(_spi, _nonos, _netapp, _flowcont), _nonos(_driver), _wlan(_driver, _wlan_filters),
      _wlan_filters(_driver), _netapp(_driver, _nonos), _fs(_driver), _netcfg(_driver),
      _socket(_driver, _nonos), _flowcont(_driver, _nonos)       
{

}
#else
cc3100::cc3100(PinName button1_irq, PinName button2_irq, PinName cc3100_irq, PinName cc3100_nHIB, PinName cc3100_cs, SPI cc3100_spi)
    : _spi(button1_irq, button2_irq, cc3100_irq, cc3100_nHIB, cc3100_cs, cc3100_spi, _driver),
      _driver(_spi, _netapp, _flowcont), _wlan(_driver, _wlan_filters),
      _wlan_filters(_driver), _netapp(_driver), _fs(_driver), _netcfg(_driver),
      _socket(_driver), _flowcont(_driver)       
{

}
#endif

cc3100::~cc3100()
{

}

/*!
    \brief This function initializes the application variables

    \param[in]  None

    \return     0 on success, negative error-code on error
*/
int32_t cc3100::initializeAppVariables()
{
    
    g_Status = 0;
    g_PingPacketsRecv = 0;
    g_StationIP = 0;
    g_GatewayIP = 0;
    g_DestinationIP = 0;
    g_BytesReceived = 0; /* variable to store the file size */
    g_SockID = 0;
    memset(g_buff, 0, sizeof(g_buff));

    return SUCCESS;
}
    
/*!
    \brief Disconnecting from a WLAN Access point

    This function disconnects from the connected AP

    \param[in]      None

    \return         none

    \note

    \warning        If the WLAN disconnection fails, we will be stuck in this function forever.
*/
int32_t cc3100::disconnectFromAP()
{
    int32_t retVal = -1;

    /*
     * The function returns 0 if 'Disconnected done', negative number if already disconnected
     * Wait for 'disconnection' event if 0 is returned, Ignore other return-codes
     */
    retVal = _wlan.sl_WlanDisconnect();
    if(0 == retVal)
    {
        /* Wait */
//#ifndef SL_PLATFORM_MULTI_THREADED
#if (!defined (SL_PLATFORM_MULTI_THREADED)) && (!defined (SL_PLATFORM_EXTERNAL_SPAWN))         
        while(IS_CONNECTED(g_Status,STATUS_BIT_CONNECTION)) { _nonos._SlNonOsMainLoopTask(); }
#endif        
    }

    return SUCCESS;
}

int32_t cc3100::Network_AP_InitDriver(){
	
    SlPingStartCommand_t PingParams = {0};
    SlPingReport_t Report = {0};

    uint8_t SecType = 0;
    int32_t role = ROLE_STA;
    int32_t retVal = -1;
    
    /*
     * Assumption is that the device is configured in station mode already
     * and it is in its default state
     */
    role = sl_Start(0, 0, 0);
    if (ROLE_AP == role) {
        /* If the device is in AP mode, we need to wait for this event before doing anything */
#if (!defined (SL_PLATFORM_MULTI_THREADED)) && (!defined (SL_PLATFORM_EXTERNAL_SPAWN))        
        while(!IS_IP_ACQUIRED(g_Status,STATUS_BIT_IP_ACQUIRED)) {
            _nonos._SlNonOsMainLoopTask();
        }
#endif        
    } else {
        /* Configure CC3100 to start in AP mode */
        retVal = _wlan.sl_WlanSetMode(ROLE_AP);
        if(retVal < 0)
            LOOP_FOREVER();
            
        /* Configure the SSID of the CC3100 */
        retVal = _wlan.sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_SSID,
                strlen(SSID_AP_MODE), (uint8_t *)SSID_AP_MODE);
        if(retVal < 0)
            LOOP_FOREVER();

        SecType = SEC_TYPE_AP_MODE;
        /* Configure the Security parameter the AP mode */
        retVal = _wlan.sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_SECURITY_TYPE, 1, (uint8_t *)&SecType);
        if(retVal < 0)
            LOOP_FOREVER();

        retVal = _wlan.sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_PASSWORD, strlen(PASSWORD_AP_MODE), (uint8_t *)PASSWORD_AP_MODE);
        if(retVal < 0)
            LOOP_FOREVER();    

        retVal = sl_Stop(SL_STOP_TIMEOUT);
        if(retVal < 0)
            LOOP_FOREVER();

        CLR_STATUS_BIT(g_Status, STATUS_BIT_IP_ACQUIRED);

        role = sl_Start(0, 0, 0);
        if (ROLE_AP == role) {
#if (!defined (SL_PLATFORM_MULTI_THREADED)) && (!defined (SL_PLATFORM_EXTERNAL_SPAWN))            
            /* If the device is in AP mode, we need to wait for this event before doing anything */
            while(!IS_IP_ACQUIRED(g_Status,STATUS_BIT_IP_ACQUIRED)) {
                _nonos._SlNonOsMainLoopTask();
            }
#endif            
        } else {
            printf(" Device couldn't be configured in AP mode \n\r");
            LOOP_FOREVER();
        }
    }
    printf(" Device started as Access Point\r\n");	
	return 0;
}	

//*****************************************************************************
//
//! Network_IF_InitDriver
//! The function initializes a CC3200 device and triggers it to start operation
//!  
//! \param  uiMode (device mode in which device will be configured)
//!  
//! \return 0 : sucess, -ve : failure
//
//*****************************************************************************
int32_t cc3100::Network_IF_InitDriver(uint32_t uiMode)
{
    int32_t lRetVal = -1;
    // Reset CC3200 Network State Machine
    initializeAppVariables();
    //
    // Following function configure the device to default state by cleaning
    // the persistent settings stored in NVMEM (viz. connection profiles &
    // policies, power policy etc)
    //
    // Applications may choose to skip this step if the developer is sure
    // that the device is in its default state at start of application
    //
    // Note that all profiles and persistent settings that were done on the
    // device will be lost
    //
    
    lRetVal = configureSimpleLinkToDefaultState();
    if(lRetVal < 0)
    {
        if (DEVICE_NOT_IN_STATION_MODE == lRetVal)
           Uart_Write((uint8_t*)"Failed to configure the device in its default state \n\r");

        LOOP_FOREVER();
    }

    Uart_Write((uint8_t*)"Device is configured in default state \n\r");

    //
    // Assumption is that the device is configured in station mode already
    // and it is in its default state
    //

    lRetVal = sl_Start(0, 0, 0);

    if (lRetVal < 0 || lRetVal != ROLE_STA)
    {
        Uart_Write((uint8_t*)"Failed to start the device \n\r");
        LOOP_FOREVER();
    }

    Uart_Write((uint8_t*)"Started SimpleLink Device: STA Mode\n\r");

    if(uiMode == ROLE_AP)
    {
        Uart_Write((uint8_t*)"Switching to AP mode on application request\n\r");
        // Switch to AP role and restart
        lRetVal = _wlan.sl_WlanSetMode(uiMode);        
        ASSERT_ON_ERROR(lRetVal);

        lRetVal = sl_Stop(0xFF);

        lRetVal = sl_Start(0, 0, 0);
        ASSERT_ON_ERROR(lRetVal);

        // Check if the device is up in AP Mode
        if (ROLE_AP == lRetVal)
        {
            // If the device is in AP mode, we need to wait for this event
            // before doing anything
            while(!IS_IP_ACQUIRED(g_Status,STATUS_BIT_IP_ACQUIRED))
            {
            		//Turn RED LED On
			GPIO_IF_LedOn(MCU_RED_LED_GPIO);
			osi_Sleep(50);

			//Turn RED LED Off
			GPIO_IF_LedOff(MCU_RED_LED_GPIO);
			osi_Sleep(50);

//#ifndef SL_PLATFORM_MULTI_THREADED
#if (!defined (SL_PLATFORM_MULTI_THREADED)) && (!defined (SL_PLATFORM_EXTERNAL_SPAWN))
              _nonos._SlNonOsMainLoopTask();
#else
              osi_Sleep(1);
#endif
            }
        }
        else
        {
            // We don't want to proceed if the device is not coming up in AP-mode
            ASSERT_ON_ERROR(DEVICE_NOT_IN_AP_MODE);
        }

        Uart_Write((uint8_t*)"Re-started SimpleLink Device: AP Mode\n\r");
    }
    else if(uiMode == ROLE_P2P)
    {
        Uart_Write((uint8_t*)"Switching to P2P mode on application request\n\r");
        // Switch to AP role and restart
        lRetVal = _wlan.sl_WlanSetMode(uiMode);
        ASSERT_ON_ERROR(lRetVal);

        lRetVal = sl_Stop(0xFF);

        lRetVal = sl_Start(0, 0, 0);
        ASSERT_ON_ERROR(lRetVal);

        // Check if the device is in station again
        if (ROLE_P2P != lRetVal)
        {
            // We don't want to proceed if the device is not coming up in P2P-mode
            ASSERT_ON_ERROR(DEVICE_NOT_IN_P2P_MODE);
        }

        Uart_Write((uint8_t*)"Re-started SimpleLink Device: P2P Mode\n\r");
    }
    else
    {
        // Device already started in STA-Mode
    }
    return 0;
}     

/*!
    \brief This function configure the SimpleLink device in its default state. It:
           - Sets the mode to STATION
           - Configures connection policy to Auto and AutoSmartConfig
           - Deletes all the stored profiles
           - Enables DHCP
           - Disables Scan policy
           - Sets Tx power to maximum
           - Sets power policy to normal
           - Unregisters mDNS services
           - Remove all filters

    \param[in]      none

    \return         On success, zero is returned. On error, negative is returned
*/
int32_t cc3100::configureSimpleLinkToDefaultState()
{
    SlVersionFull   ver = {0};
    _WlanRxFilterOperationCommandBuff_t  RxFilterIdMask = {0};
    
    uint8_t           val = 1;
    uint8_t           configOpt = 0;
    uint8_t           configLen = 0;
    uint8_t           power = 0;

    int32_t          retVal = -1;
    int32_t          role = -1;

    role = sl_Start(0, 0, 0);
    ASSERT_ON_ERROR(role);

    /* If the device is not in station-mode, try configuring it in station-mode */
    if (ROLE_STA != role) {
        if (ROLE_AP == role) {
            /* If the device is in AP mode, we need to wait for this event before doing anything */
//#ifndef SL_PLATFORM_MULTI_THREADED
#if (!defined (SL_PLATFORM_MULTI_THREADED)) && (!defined (SL_PLATFORM_EXTERNAL_SPAWN))            
            while(!IS_IP_ACQUIRED(g_Status,STATUS_BIT_IP_ACQUIRED)) {
                _nonos._SlNonOsMainLoopTask();
            }
#endif            
        }
       
        /* Switch to STA role and restart */
        retVal = _wlan.sl_WlanSetMode(ROLE_STA);
        ASSERT_ON_ERROR(retVal);
    
        retVal = sl_Stop(SL_STOP_TIMEOUT);
        ASSERT_ON_ERROR(retVal);
    
        retVal = sl_Start(0, 0, 0);
        ASSERT_ON_ERROR(retVal);
    
        /* Check if the device is in station again */
        if (ROLE_STA != retVal) {
            /* We don't want to proceed if the device is not coming up in station-mode */
            ASSERT_ON_ERROR(DEVICE_NOT_IN_STATION_MODE);
        }
    }
    
    /* Get the device's version-information */
    configOpt = SL_DEVICE_GENERAL_VERSION;
    configLen = sizeof(ver);
    retVal = sl_DevGet(SL_DEVICE_GENERAL_CONFIGURATION, &configOpt, &configLen, (uint8_t *)(&ver));
    ASSERT_ON_ERROR(retVal);
    
    /* Set connection policy to Auto + SmartConfig (Device's default connection policy) */
    retVal = _wlan.sl_WlanPolicySet(SL_POLICY_CONNECTION, SL_CONNECTION_POLICY(1, 0, 0, 0, 1), NULL, 0);
    ASSERT_ON_ERROR(retVal);
    
    /* Remove all profiles */
    retVal = _wlan.sl_WlanProfileDel(0xFF);
    ASSERT_ON_ERROR(retVal);

    /*
     * Device in station-mode. Disconnect previous connection if any
     * The function returns 0 if 'Disconnected done', negative number if already disconnected
     * Wait for 'disconnection' event if 0 is returned, Ignore other return-codes
     */
    retVal = _wlan.sl_WlanDisconnect();
    if(0 == retVal) {
        /* Wait */
//#ifndef SL_PLATFORM_MULTI_THREADED
#if (!defined (SL_PLATFORM_MULTI_THREADED)) && (!defined (SL_PLATFORM_EXTERNAL_SPAWN))        
        while(IS_CONNECTED(g_Status,STATUS_BIT_CONNECTION)) {
            _nonos._SlNonOsMainLoopTask();
        }
#endif        
    }
    
    /* Enable DHCP client*/
    retVal = _netcfg.sl_NetCfgSet(SL_IPV4_STA_P2P_CL_DHCP_ENABLE,1,1,&val);
    ASSERT_ON_ERROR(retVal);
    
    /* Disable scan */
    configOpt = SL_SCAN_POLICY(0);
    retVal = _wlan.sl_WlanPolicySet(SL_POLICY_SCAN , configOpt, NULL, 0);
    ASSERT_ON_ERROR(retVal);
    
    /* Set Tx power level for station mode
       Number between 0-15, as dB offset from maximum power - 0 will set maximum power */
    power = 0;
    retVal = _wlan.sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID, WLAN_GENERAL_PARAM_OPT_STA_TX_POWER, 1, (uint8_t *)&power);
    ASSERT_ON_ERROR(retVal);

    /* Set PM policy to normal */
    retVal = _wlan.sl_WlanPolicySet(SL_POLICY_PM , SL_NORMAL_POLICY, NULL, 0);
    ASSERT_ON_ERROR(retVal);

    /* Unregister mDNS services */
    retVal = _netapp.sl_NetAppMDNSUnRegisterService(0, 0);
    ASSERT_ON_ERROR(retVal);

    /* Remove  all 64 filters (8*8) */
    memset(RxFilterIdMask.FilterIdMask, 0xFF, 8);

    retVal = _wlan_filters.sl_WlanRxFilterSet(SL_REMOVE_RX_FILTER, (uint8_t *)&RxFilterIdMask,
             sizeof(_WlanRxFilterOperationCommandBuff_t));
    ASSERT_ON_ERROR(retVal);

    retVal = sl_Stop(SL_STOP_TIMEOUT);
    ASSERT_ON_ERROR(retVal);

    retVal = initializeAppVariables();
    ASSERT_ON_ERROR(retVal);

    return retVal; /* Success */
}

/*!
    \brief Create UDP socket to communicate with server.

    \param[in]      none

    \return         Socket descriptor for success otherwise negative

    \warning
*/
int32_t cc3100::createUDPConnection()
{
    int32_t sd = 0;

    sd = _socket.sl_Socket(SL_AF_INET, SL_SOCK_DGRAM, IPPROTO_UDP);
    if( sd < 0 )
    {
        Uart_Write((uint8_t *)"Error creating socket\n\r\n\r");
    }

    return sd;
}	

/*!
    \brief Create connection with server.

    This function opens a socket and create the endpoint communication with server

    \param[in]      DestinationIP - IP address of the server

    \return         socket id for success and negative for error
*/
int32_t cc3100::createConnection(uint32_t DestinationIP)
{
    SlSockAddrIn_t  Addr = {0};
    int32_t           Status = 0;
    int32_t           AddrSize = 0;
    int32_t           SockID = 0;

    Addr.sin_family = SL_AF_INET;
    Addr.sin_port = _socket.sl_Htons(80);
    Addr.sin_addr.s_addr = _socket.sl_Htonl(DestinationIP);

    AddrSize = sizeof(SlSockAddrIn_t);

    SockID = _socket.sl_Socket(SL_AF_INET,SL_SOCK_STREAM, 0);
    ASSERT_ON_ERROR(SockID);

    Status = _socket.sl_Connect(SockID, ( SlSockAddr_t *)&Addr, AddrSize);
    if (Status < 0)
    {
        _socket.sl_Close(SockID);
        ASSERT_ON_ERROR(Status);
    }

    return SockID;
}

/*!
    \brief Convert hex to decimal base

    \param[in]      ptr - pointer to string containing number in hex

    \return         number in decimal base

*/
int32_t cc3100::hexToi(unsigned char *ptr)
{
    uint32_t result = 0;
    uint32_t len = 0;

    int32_t  idx = -1;

    len = strlen((const char*) ptr);

    /* convert characters to upper case */
    for(idx = 0; ptr[idx] != '\0'; ++idx)
    {
        if( (ptr[idx] >= 'a') &&
            (ptr[idx] <= 'f') )
        {
            ptr[idx] -= 32;         /* Change case - ASCII 'a' = 97, 'A' = 65 => 97-65 = 32 */
        }
    }

    for(idx = 0; ptr[idx] != '\0'; ++idx)
    {
        if(ptr[idx] >= '0' && ptr[idx] <= '9')
        {
            /* Converting '0' to '9' to their decimal value */
            result += (ptr[idx] - '0') * (1 << (4 * (len - 1 - idx)));
        }
        else if(ptr[idx] >= 'A' && ptr[idx] <= 'F')
        {
            /* Converting hex 'A' to 'F' to their decimal value */
            result += (ptr[idx] - 55) * (1 << (4 * (len -1 - idx))); /* .i.e. 'A' - 55 = 10, 'F' - 55 = 15 */
        }
        else
        {
            ASSERT_ON_ERROR(INVALID_HEX_STRING);
        }
    }

    return result;
}

/*!
    \brief Calculate the file chunk size

    \param[in]      len - pointer to length of the data in the buffer
    \param[in]      p_Buff - pointer to pointer of buffer containing data
    \param[out]     chunk_size - pointer to variable containing chunk size

    \return         0 for success, -ve for error

*/
int32_t cc3100::getChunkSize(int32_t *len, uint8_t **p_Buff, uint32_t *chunk_size)
{
    int32_t   idx = -1;
    unsigned char   lenBuff[10];

    idx = 0;
    memset(lenBuff, 0, sizeof(lenBuff));
    while(*len >= 0 && **p_Buff != 13) /* check for <CR> */
    {
        if(0 == *len)
        {
            memset(g_buff, 0, sizeof(g_buff));
            *len = _socket.sl_Recv(g_SockID, &g_buff[0], MAX_BUFF_SIZE, 0);
            if(*len <= 0)
                ASSERT_ON_ERROR(TCP_RECV_ERROR);

            *p_Buff = g_buff;
        }

        lenBuff[idx] = **p_Buff;
        idx++;
        (*p_Buff)++;
        (*len)--;
    }

    (*p_Buff) += 2; /* skip <CR><LF> */
    (*len) -= 2;
    *chunk_size = hexToi(lenBuff);

    return SUCCESS;
}

/*!
    \brief Obtain the file from the server

    This function requests the file from the server and save it on serial flash.
    To request a different file for different user needs to modify the
    PREFIX_BUFFER and POST_BUFFER macros.

    \param[in]      None

    \return         0 for success and negative for error

*/
/*
int32_t cc3100::getFile()
{
    uint32_t Token = 0;
    uint32_t recv_size = 0;
    uint8_t *pBuff = 0;
    uint8_t eof_detected = 0;
    uint8_t isChunked = 0;

    int32_t transfer_len = -1;
    int32_t retVal = -1;
    int32_t fileHandle = -1;

    memset(g_buff, 0, sizeof(g_buff));

    //Puts together the HTTP GET string.
    strcpy((char*)g_buff, PREFIX_BUFFER);
    strcat((char*)g_buff, POST_BUFFER);

    //Send the HTTP GET string to the opened TCP/IP socket.
    transfer_len = _socket.sl_Send(g_SockID, g_buff, strlen((const char*)g_buff), 0);

    if (transfer_len < 0)
    {
        // error 
        printf(" Socket Send Error\r\n");
        ASSERT_ON_ERROR(TCP_SEND_ERROR);
    }

    memset(g_buff, 0, sizeof(g_buff));

    //get the reply from the server in buffer.
    transfer_len = _socket.sl_Recv(g_SockID, &g_buff[0], MAX_BUFF_SIZE, 0);

    if(transfer_len <= 0)
        ASSERT_ON_ERROR(TCP_RECV_ERROR);

    // Check for 404 return code 
    if(strstr((const char*)g_buff, HTTP_FILE_NOT_FOUND) != 0)
    {
        printf(" File not found, check the file and try again\r\n");
        ASSERT_ON_ERROR(FILE_NOT_FOUND_ERROR);
    }

    // if not "200 OK" return error 
    if(strstr((const char*)g_buff, HTTP_STATUS_OK) == 0)
    {
        printf(" Error during downloading the file\r\n");
        ASSERT_ON_ERROR(INVALID_SERVER_RESPONSE);
    }

    // check if content length is transferred with headers 
    pBuff = (uint8_t *)strstr((const char*)g_buff, HTTP_CONTENT_LENGTH);
    if(pBuff != 0)
    {
        // not supported 
        printf(" Server response format is not supported\r\n");
        ASSERT_ON_ERROR(FORMAT_NOT_SUPPORTED);
    }

    // Check if data is chunked 
    pBuff = (uint8_t *)strstr((const char*)g_buff, HTTP_TRANSFER_ENCODING);
    if(pBuff != 0)
    {
        pBuff += strlen(HTTP_TRANSFER_ENCODING);
        while(*pBuff == SPACE)
            pBuff++;

        if(memcmp(pBuff, HTTP_ENCODING_CHUNKED, strlen(HTTP_ENCODING_CHUNKED)) == 0)
        {
            recv_size = 0;
            isChunked = 1;
        }
    }
    else
    {
        // Check if connection will be closed by after sending data
         // In this method the content length is not received and end of
         // connection marks the end of data 
        pBuff = (uint8_t *)strstr((const char*)g_buff, HTTP_CONNECTION);
        if(pBuff != 0)
        {
            pBuff += strlen(HTTP_CONNECTION);
            while(*pBuff == SPACE)
                pBuff++;

            if(memcmp(pBuff, HTTP_ENCODING_CHUNKED, strlen(HTTP_CONNECTION_CLOSE)) == 0)
            {
                // not supported 
                printf(" Server response format is not supported\r\n");
                ASSERT_ON_ERROR(FORMAT_NOT_SUPPORTED);
            }
        }
    }

    // "\r\n\r\n" marks the end of headers 
    pBuff = (uint8_t *)strstr((const char*)g_buff, HTTP_END_OF_HEADER);
    if(pBuff == 0)
    {
        printf(" Invalid response\r\n");
        ASSERT_ON_ERROR(INVALID_SERVER_RESPONSE);
    }
    // Increment by 4 to skip "\r\n\r\n" 
    pBuff += 4;

    // Adjust buffer data length for header size 
    transfer_len -= (pBuff - g_buff);

    // If data in chunked format, calculate the chunk size 
    if(isChunked == 1)
    {
        retVal = getChunkSize(&transfer_len, &pBuff, &recv_size);
        if(retVal < 0)
        {
            // Error 
            printf(" Problem with connection to server\r\n");
            return retVal;
        }
    }

    // Open file to save the downloaded file 
    retVal = _fs.sl_FsOpen((uint8_t *)FILE_NAME,
                       FS_MODE_OPEN_WRITE, &Token, &fileHandle);
    if(retVal < 0)
    {
        // File Doesn't exit create a new of 45 KB file 
        retVal = _fs.sl_FsOpen((uint8_t *)FILE_NAME,
                           _fs.FS_MODE_OPEN_CREATE(SIZE_45K,_FS_FILE_OPEN_FLAG_COMMIT|_FS_FILE_PUBLIC_WRITE),
                           &Token, &fileHandle);
        if(retVal < 0)
        {
            printf(" Error during opening the file\r\n");
            return retVal;
        }
    }

    while (0 < transfer_len)
    {
        // For chunked data recv_size contains the chunk size to be received
         // while the transfer_len contains the data in the buffer 
        if(recv_size <= transfer_len)
        {
            // write the recv_size 
            retVal = _fs.sl_FsWrite(fileHandle, g_BytesReceived,
                    (uint8_t *)pBuff, recv_size);
            if(retVal < recv_size)
            {
                // Close file without saving 
                retVal = _fs.sl_FsClose(fileHandle, 0, (unsigned char*)"A", 1);
                printf(" Error during writing the file\r\n");
                return FILE_WRITE_ERROR;
            }
            transfer_len -= recv_size;
            g_BytesReceived +=recv_size;
            pBuff += recv_size;
            recv_size = 0;

            if(isChunked == 1)
            {
                // if data in chunked format calculate next chunk size 
                pBuff += 2; // 2 bytes for <CR> <LF> 
                transfer_len -= 2;

                if(getChunkSize(&transfer_len, &pBuff, &recv_size) < 0)
                {
                    // Error 
                    break;
                }

                // if next chunk size is zero we have received the complete file 
                if(recv_size == 0)
                {
                    eof_detected = 1;
                    break;
                }

                if(recv_size < transfer_len)
                {
                    // Code will enter this section if the new chunk size is less then
                     // then the transfer size. This will the last chunk of file received
                     
                    retVal = _fs.sl_FsWrite(fileHandle, g_BytesReceived,
                            (uint8_t *)pBuff, recv_size);
                    if(retVal < recv_size)
                    {
                        // Close file without saving 
                        retVal = _fs.sl_FsClose(fileHandle, 0, (unsigned char*)"A", 1);
                        printf(" Error during writing the file\r\n");
                        return FILE_WRITE_ERROR;
                    }
                    transfer_len -= recv_size;
                    g_BytesReceived +=recv_size;
                    pBuff += recv_size;
                    recv_size = 0;

                    pBuff += 2; // 2bytes for <CR> <LF> 
                    transfer_len -= 2;

                    // Calculate the next chunk size, should be zero 
                    if(getChunkSize(&transfer_len, &pBuff, &recv_size) < 0)
                    {
                        // Error 
                        break;
                    }

                    // if next chunk size is non zero error 
                    if(recv_size != 0)
                    {
                        // Error 
                        break;
                    }
                    eof_detected = 1;
                    break;
                }
                else
                {
                    // write data on the file 
                    retVal = _fs.sl_FsWrite(fileHandle, g_BytesReceived,
                            (uint8_t *)pBuff, transfer_len);
                    if(retVal < transfer_len)
                    {
                        // Close file without saving 
                        retVal = _fs.sl_FsClose(fileHandle, 0, (unsigned char*)"A", 1);
                        printf(" Error during writing the file\r\n");
                        ASSERT_ON_ERROR(FILE_WRITE_ERROR);
                    }
                    recv_size -= transfer_len;
                    g_BytesReceived +=transfer_len;
                }
            }
            // complete file received exit 
            if(recv_size == 0)
            {
                eof_detected = 1;
                break;
            }
        }
        else
        {
            // write data on the file 
            retVal = _fs.sl_FsWrite(fileHandle, g_BytesReceived,
                                 (uint8_t *)pBuff, transfer_len);
            if (retVal < 0)
            {
                // Close file without saving 
                retVal = _fs.sl_FsClose(fileHandle, 0, (unsigned char*)"A", 1);
                printf(" Error during writing the file\r\n");
                ASSERT_ON_ERROR(FILE_WRITE_ERROR);
            }
            g_BytesReceived +=transfer_len;
            recv_size -= transfer_len;
        }

        memset(g_buff, 0, sizeof(g_buff));

        transfer_len = _socket.sl_Recv(g_SockID, &g_buff[0], MAX_BUFF_SIZE, 0);
        if(transfer_len <= 0)
            ASSERT_ON_ERROR(TCP_RECV_ERROR);

        pBuff = g_buff;
    }

    // If user file has checksum which can be used to verify the temporary
     // file then file should be verified
     // In case of invalid file (FILE_NAME) should be closed without saving to
     // recover the previous version of file 
    if(0 > transfer_len || eof_detected == 0)
    {
        // Close file without saving 
        retVal = _fs.sl_FsClose(fileHandle, 0, (unsigned char*)"A", 1);
        printf(" Error While File Download\r\n");
        ASSERT_ON_ERROR(INVALID_FILE);
    }
    else
    {
        // Save and close file 
        retVal = _fs.sl_FsClose(fileHandle, 0, 0, 0);
        ASSERT_ON_ERROR(retVal);
    }

    return SUCCESS;;
}
*/

/*!
    \brief Connecting to a WLAN Access point

    This function connects to the required AP (SSID_NAME).
    The function will return once we are connected and have acquired IP address

    \param[in]  None

    \return     0 on success, negative error-code on error

    \note

    \warning    If the WLAN connection fails or we don't acquire an IP address,
                We will be stuck in this function forever.
*/
int32_t cc3100::establishConnectionWithAP()
{
    
    SlSecParams_t secParams = {0};
    int32_t retVal = 0;

    secParams.Key = (signed char *)PASSKEY;
    secParams.KeyLen = strlen(PASSKEY);
    secParams.Type = SEC_TYPE;

    retVal = _wlan.sl_WlanConnect((signed char *)SSID_NAME, strlen(SSID_NAME), 0, &secParams, 0);
    ASSERT_ON_ERROR(retVal);
    
    /* Wait */
//#ifndef SL_PLATFORM_MULTI_THREADED 
#if (!defined (SL_PLATFORM_MULTI_THREADED)) && (!defined (SL_PLATFORM_EXTERNAL_SPAWN))   
    while((!IS_CONNECTED(g_Status,STATUS_BIT_CONNECTION)) || (!IS_IP_ACQUIRED(g_Status,STATUS_BIT_IP_ACQUIRED))) { _nonos._SlNonOsMainLoopTask(); }
#endif
    return SUCCESS;
}

/*!
    \brief This function checks the LAN connection by pinging the AP's gateway

    \param[in]  None

    \return     0 on success, negative error-code on error
*/
int32_t cc3100::checkLanConnection()
{
    SlPingStartCommand_t pingParams = {0};
    SlPingReport_t pingReport = {0};

    int32_t retVal = -1;

    CLR_STATUS_BIT(g_Status, STATUS_BIT_PING_DONE);
    g_PingPacketsRecv = 0;

    /* Set the ping parameters */
    pingParams.PingIntervalTime = PING_INTERVAL;
    pingParams.PingSize = PING_PKT_SIZE;
    pingParams.PingRequestTimeout = PING_TIMEOUT;
    pingParams.TotalNumberOfAttempts = PING_ATTEMPTS;
    pingParams.Flags = 0;
    pingParams.Ip = g_GatewayIP;

    /* Check for LAN connection */
    retVal = _netapp.sl_NetAppPingStart( (SlPingStartCommand_t*)&pingParams, SL_AF_INET,
                                 (SlPingReport_t*)&pingReport, SimpleLinkPingReport);
    ASSERT_ON_ERROR(retVal);

    /* Wait */
//#ifndef SL_PLATFORM_MULTI_THREADED 
#if (!defined (SL_PLATFORM_MULTI_THREADED)) && (!defined (SL_PLATFORM_EXTERNAL_SPAWN))   
    while(!IS_PING_DONE(g_Status,STATUS_BIT_PING_DONE)) { _nonos._SlNonOsMainLoopTask(); }
#endif    

    if(0 == g_PingPacketsRecv)
    {
        /* Problem with LAN connection */
        ASSERT_ON_ERROR(LAN_CONNECTION_FAILED);
    }

    /* LAN connection is successful */
    return SUCCESS;
}

/*!
    \brief This function checks the internet connection by pinging
           the external-host (HOST_NAME)

    \param[in]  None

    \return     0 on success, negative error-code on error
*/
int32_t cc3100::checkInternetConnection()
{
    SlPingStartCommand_t pingParams = {0};
    SlPingReport_t pingReport = {0};

    uint32_t ipAddr = 0;

    int32_t retVal = -1;

    CLR_STATUS_BIT(g_Status, STATUS_BIT_PING_DONE);
    g_PingPacketsRecv = 0;

    /* Set the ping parameters */
    pingParams.PingIntervalTime = PING_INTERVAL;
    pingParams.PingSize = PING_PKT_SIZE;
    pingParams.PingRequestTimeout = PING_TIMEOUT;
    pingParams.TotalNumberOfAttempts = PING_ATTEMPTS;
    pingParams.Flags = 0;
    pingParams.Ip = g_GatewayIP;

    /* Check for Internet connection */
    retVal = _netapp.sl_NetAppDnsGetHostByName((unsigned char *)HOST_NAME, strlen(HOST_NAME), &ipAddr, SL_AF_INET);
    ASSERT_ON_ERROR(retVal);

    /* Replace the ping address to match HOST_NAME's IP address */
    pingParams.Ip = ipAddr;

    /* Try to ping HOST_NAME */
    retVal = _netapp.sl_NetAppPingStart( (SlPingStartCommand_t*)&pingParams, SL_AF_INET,
                                 (SlPingReport_t*)&pingReport, SimpleLinkPingReport);
    ASSERT_ON_ERROR(retVal);

    /* Wait */
//#ifndef SL_PLATFORM_MULTI_THREADED
#if (!defined (SL_PLATFORM_MULTI_THREADED)) && (!defined (SL_PLATFORM_EXTERNAL_SPAWN))    
    while(!IS_PING_DONE(g_Status,STATUS_BIT_PING_DONE)) { _nonos._SlNonOsMainLoopTask(); }
#endif    

    if (0 == g_PingPacketsRecv)
    {
        /* Problem with internet connection*/
        ASSERT_ON_ERROR(INTERNET_CONNECTION_FAILED);
    }

    /* Internet connection is successful */
    return SUCCESS;
}

const int8_t StartResponseLUT[8] = 
{
    ROLE_UNKNOWN_ERR,
    ROLE_STA,
    ROLE_STA_ERR,
    ROLE_AP,
    ROLE_AP_ERR,
    ROLE_P2P,
    ROLE_P2P_ERR,
    ROLE_UNKNOWN_ERR    
};
    
/*****************************************************************************/
/* Internal functions                                                        */
/*****************************************************************************/

int16_t cc3100::_sl_GetStartResponseConvert(uint32_t Status)
{
    return (int16_t)StartResponseLUT[Status & 0x7];
    
}

/*****************************************************************************/
/* API Functions                                                             */
/*****************************************************************************/

bool cc3100::IS_PING_DONE(uint32_t status_variable,const uint32_t bit){
	
	    g_Status = status_variable;
	    
	    if(0 != (g_Status & ((uint32_t)1L<<(bit)))){
	    	return TRUE;
        }else{
        	return FALSE;
        }
}
        
bool cc3100::IS_CONNECTED(uint32_t status_variable,const uint32_t bit){
	
	    g_Status = status_variable;
	    
	    if(0 != (g_Status & ((uint32_t)1L<<(bit)))){
	    	return TRUE;
        }else{
        	return FALSE;
        }
}
        
bool cc3100::IS_STA_CONNECTED(uint32_t status_variable,const uint32_t bit){
	
	    g_Status = status_variable;
	    
	    if(0 != (g_Status & ((uint32_t)1L<<(bit)))){
	    	return TRUE;
        }else{
        	return FALSE;
        }
} 
       
bool cc3100::IS_IP_ACQUIRED(uint32_t status_variable,const uint32_t bit){
	
	    g_Status = status_variable;
	    
	    if(0 != (g_Status & ((uint32_t)1L<<(bit)))){
	    	return TRUE;
        }else{
        	return FALSE;
        }
}
        
bool cc3100::IS_IP_LEASED(uint32_t status_variable,const uint32_t bit){
	
	    g_Status = status_variable;
	    
	    if(0 != (g_Status & ((uint32_t)1L<<(bit)))){
	    	return TRUE;
        }else{
        	return FALSE;
        }
}
        
bool cc3100::IS_CONNECTION_FAILED(uint32_t status_variable,const uint32_t bit){
	    
	    g_Status = status_variable;
	    
	    if(0 != (g_Status & ((uint32_t)1L<<(bit)))){
	    	return TRUE;
        }else{
        	return FALSE;
        }
}
        
bool cc3100::IS_P2P_NEG_REQ_RECEIVED(uint32_t status_variable,const uint32_t bit){
	
	    g_Status = status_variable;
	    
	    if(0 != (g_Status & ((uint32_t)1L<<(bit)))){
	    	return TRUE;
        }else{
        	return FALSE;
        }
}
        
bool cc3100::IS_SMARTCONFIG_DONE(uint32_t status_variable,const uint32_t bit){
	
	    g_Status = status_variable;
	    
	    if(0 != (g_Status & ((uint32_t)1L<<(bit)))){
	    	return TRUE;
        }else{
        	return FALSE;
        }
}
        
bool cc3100::IS_SMARTCONFIG_STOPPED(uint32_t status_variable,const uint32_t bit){
	
	    g_Status = status_variable;
	    
	    if(0 != (g_Status & ((uint32_t)1L<<(bit)))){	    	
	    	return TRUE;
        }else{
        	return FALSE;       	
        }        
}

void cc3100::CLR_STATUS_BIT(uint32_t status_variable, const uint32_t bit){
	    
	    g_Status = status_variable;
	    g_Status &= ~((uint32_t)1L<<(bit));
	    
}

void cc3100::SET_STATUS_BIT(uint32_t status_variable, const uint32_t bit){

	    g_Status = status_variable;
	    g_Status |= ((uint32_t)1L<<(bit));
	    
}
void cc3100::CLR_STATUS_BIT_ALL(uint32_t status_variable){
      
      g_Status = status_variable;
      g_Status = 0;
}      
	    
/*****************************************************************************/
/* sl_Task                                                                   */
/*****************************************************************************/
#if _SL_INCLUDE_FUNC(sl_Task)
void cc3100::sl_Task(void)
{
#ifdef _SlTaskEntry
    _SlTaskEntry();
#endif
}
#endif

/*****************************************************************************/
/* sl_Start                                                                  */
/*****************************************************************************/
#if _SL_INCLUDE_FUNC(sl_Start)
int16_t cc3100::sl_Start(const void* pIfHdl, int8_t*  pDevName, const P_INIT_CALLBACK pInitCallBack)
{
    int16_t ObjIdx = MAX_CONCURRENT_ACTIONS;
    InitComplete_t  AsyncRsp;

    /* Perform any preprocessing before enable networking services */
    sl_DeviceEnablePreamble();//stub only
    
    /* ControlBlock init */
    _driver._SlDrvDriverCBInit();
    
    /* open the interface: usually SPI or UART */
    if (NULL == pIfHdl) 
    {
        g_pCB->FD = _spi.spi_Open((int8_t *)pDevName, 0);
    } 
    else 
    {
        g_pCB->FD = (_SlFd_t)pIfHdl;
    }
     
    ObjIdx = _driver._SlDrvProtectAsyncRespSetting((uint8_t *)&AsyncRsp, START_STOP_ID, SL_MAX_SOCKETS);
    
    if (MAX_CONCURRENT_ACTIONS == ObjIdx) 
    {
        Uart_Write((uint8_t *)"SL_POOL_IS_EMPTY\r\n");
        return SL_POOL_IS_EMPTY;
    }
    
    if( g_pCB->FD >= (_SlFd_t)0) {
        _spi.CC3100_disable();
        
        g_pCB->pInitCallback = pInitCallBack;
            
        _spi.CC3100_enable();
        
        if (NULL == pInitCallBack) {            
            _driver._SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj);            
            /*release Pool Object*/           
            _driver._SlDrvReleasePoolObj(g_pCB->FunctionParams.AsyncExt.ActionIndex);                      
            return _sl_GetStartResponseConvert(AsyncRsp.Status);
        }
        else
        {
            return SL_RET_CODE_OK;    
        }
    }
    
    return SL_BAD_INTERFACE;


}
#endif

/***************************************************************************
_sl_HandleAsync_InitComplete - handles init complete signalling to
a waiting object
****************************************************************************/
void cc3100::_sl_HandleAsync_InitComplete(void *pVoidBuf)
{

    InitComplete_t *pMsgArgs = (InitComplete_t *)_SL_RESP_ARGS_START(pVoidBuf);

    _driver._SlDrvProtectionObjLockWaitForever();

    if(g_pCB->pInitCallback) {
        g_pCB->pInitCallback(_sl_GetStartResponseConvert(pMsgArgs->Status));
    } else {
        memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs, sizeof(InitComplete_t));        
        _driver._SlDrvSyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj);
    }
    _driver._SlDrvProtectionObjUnLock();

    if(g_pCB->pInitCallback) {
        _driver._SlDrvReleasePoolObj(g_pCB->FunctionParams.AsyncExt.ActionIndex);
    }

}

/*****************************************************************************
sl_stop
******************************************************************************/
typedef union {
    _DevStopCommand_t  Cmd;
    _BasicResponse_t   Rsp;
} _SlStopMsg_u;

const _SlCmdCtrl_t _SlStopCmdCtrl = {
    SL_OPCODE_DEVICE_STOP_COMMAND,
    sizeof(_DevStopCommand_t),
    sizeof(_BasicResponse_t)
};

#if _SL_INCLUDE_FUNC(sl_Stop)
int16_t cc3100::sl_Stop(const uint16_t timeout)
{
    
    int16_t RetVal=0;
    _SlStopMsg_u      Msg;
    _BasicResponse_t  AsyncRsp;
    int8_t ObjIdx = MAX_CONCURRENT_ACTIONS;
    /* if timeout is 0 the shutdown is forced immediately */
    if( 0 == timeout ) {
        _spi.registerInterruptHandler(NULL, NULL);
        _spi.CC3100_disable();
        RetVal = _spi.spi_Close(g_pCB->FD);

    } else {
        /* let the device make the shutdown using the defined timeout */
        Msg.Cmd.Timeout = timeout;        
        ObjIdx = _driver._SlDrvProtectAsyncRespSetting((uint8_t *)&AsyncRsp, START_STOP_ID, SL_MAX_SOCKETS);
        
      if (MAX_CONCURRENT_ACTIONS == ObjIdx)
      {
          return SL_POOL_IS_EMPTY;
      }

      VERIFY_RET_OK(_driver._SlDrvCmdOp((_SlCmdCtrl_t *)&_SlStopCmdCtrl, &Msg, NULL));

      if(SL_OS_RET_CODE_OK == (int16_t)Msg.Rsp.status)
      {
         _driver._SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj);
         Msg.Rsp.status = AsyncRsp.status;
         RetVal = Msg.Rsp.status;
      }
      
      _driver._SlDrvReleasePoolObj((uint8_t)ObjIdx);
      _spi.registerInterruptHandler(NULL, NULL);
      _spi.CC3100_disable();
      _spi.spi_Close(g_pCB->FD);
     
    }
    
    _driver._SlDrvDriverCBDeinit();

    return RetVal;
}
#endif


/*****************************************************************************
sl_EventMaskSet
*****************************************************************************/
typedef union {
    _DevMaskEventSetCommand_t	    Cmd;
    _BasicResponse_t	            Rsp;
} _SlEventMaskSetMsg_u;

#if _SL_INCLUDE_FUNC(sl_EventMaskSet)
const _SlCmdCtrl_t _SlEventMaskSetCmdCtrl = {
    SL_OPCODE_DEVICE_EVENTMASKSET,
    sizeof(_DevMaskEventSetCommand_t),
    sizeof(_BasicResponse_t)
};

int16_t cc3100::sl_EventMaskSet(uint8_t EventClass , uint32_t Mask)
{
    _SlEventMaskSetMsg_u Msg;
    Msg.Cmd.group = EventClass;
    Msg.Cmd.mask = Mask;

    VERIFY_RET_OK(_driver._SlDrvCmdOp((_SlCmdCtrl_t *)&_SlEventMaskSetCmdCtrl, &Msg, NULL));

    return (int16_t)Msg.Rsp.status;
}
#endif

/******************************************************************************
sl_EventMaskGet
******************************************************************************/
typedef union {
    _DevMaskEventGetCommand_t	    Cmd;
    _DevMaskEventGetResponse_t      Rsp;
} _SlEventMaskGetMsg_u;

#if _SL_INCLUDE_FUNC(sl_EventMaskGet)
const _SlCmdCtrl_t _SlEventMaskGetCmdCtrl = {
    SL_OPCODE_DEVICE_EVENTMASKGET,
    sizeof(_DevMaskEventGetCommand_t),
    sizeof(_DevMaskEventGetResponse_t)
};

int16_t cc3100::sl_EventMaskGet(uint8_t EventClass, uint32_t *pMask)
{
    _SlEventMaskGetMsg_u Msg;

    Msg.Cmd.group = EventClass;

    VERIFY_RET_OK(_driver._SlDrvCmdOp((_SlCmdCtrl_t *)&_SlEventMaskGetCmdCtrl, &Msg, NULL));

    *pMask = Msg.Rsp.mask;
    return SL_RET_CODE_OK;
}
#endif

/******************************************************************************
sl_DevGet
******************************************************************************/

typedef union {
    _DeviceSetGet_t	    Cmd;
    _DeviceSetGet_t	    Rsp;
} _SlDeviceMsgGet_u;

#if _SL_INCLUDE_FUNC(sl_DevGet)
const _SlCmdCtrl_t _SlDeviceGetCmdCtrl = {
    SL_OPCODE_DEVICE_DEVICEGET,
    sizeof(_DeviceSetGet_t),
    sizeof(_DeviceSetGet_t)
};

int32_t cc3100::sl_DevGet(uint8_t DeviceGetId, uint8_t *pOption,uint8_t *pConfigLen, uint8_t *pValues)
{
    _SlDeviceMsgGet_u         Msg;
    _SlCmdExt_t               CmdExt;
    
    if (*pConfigLen == 0) {
        return SL_EZEROLEN;
    }
   
    if( pOption ) {
        _driver._SlDrvResetCmdExt(&CmdExt);
        CmdExt.RxPayloadLen = *pConfigLen;
        
        CmdExt.pRxPayload = (uint8_t *)pValues;
        

        Msg.Cmd.DeviceSetId = DeviceGetId;

        Msg.Cmd.Option   = (uint16_t)*pOption;

        VERIFY_RET_OK(_driver._SlDrvCmdOp((_SlCmdCtrl_t *)&_SlDeviceGetCmdCtrl, &Msg, &CmdExt));
        
        if( pOption ) {
            *pOption = (uint8_t)Msg.Rsp.Option;
        }
        
        if (CmdExt.RxPayloadLen < CmdExt.ActualRxPayloadLen) {
            *pConfigLen = (uint8_t)CmdExt.RxPayloadLen;
            return SL_ESMALLBUF;
        } else {
            *pConfigLen = (uint8_t)CmdExt.ActualRxPayloadLen;
        }
        
        return (int16_t)Msg.Rsp.Status;
    } else {
        return -1;
    }
}
#endif

/******************************************************************************
sl_DevSet
******************************************************************************/
typedef union {
    _DeviceSetGet_t    Cmd;
    _BasicResponse_t   Rsp;
} _SlDeviceMsgSet_u;

#if _SL_INCLUDE_FUNC(sl_DevSet)
const _SlCmdCtrl_t _SlDeviceSetCmdCtrl = {
    SL_OPCODE_DEVICE_DEVICESET,
    sizeof(_DeviceSetGet_t),
    sizeof(_BasicResponse_t)
};

int32_t cc3100::sl_DevSet(const uint8_t DeviceSetId, const uint8_t Option, const uint8_t ConfigLen, const uint8_t *pValues)
{
    _SlDeviceMsgSet_u         Msg;
    _SlCmdExt_t               CmdExt;
    
    _driver._SlDrvResetCmdExt(&CmdExt);
    CmdExt.TxPayloadLen = (ConfigLen+3) & (~3);
    
    CmdExt.pTxPayload = (uint8_t *)pValues;
    


    Msg.Cmd.DeviceSetId    = DeviceSetId;
    Msg.Cmd.ConfigLen   = ConfigLen;
    Msg.Cmd.Option   = Option;

    VERIFY_RET_OK(_driver._SlDrvCmdOp((_SlCmdCtrl_t *)&_SlDeviceSetCmdCtrl, &Msg, &CmdExt));

    return (int16_t)Msg.Rsp.status;
}
#endif

/******************************************************************************
sl_UartSetMode
******************************************************************************/
#ifdef SL_IF_TYPE_UART
typedef union {
    _DevUartSetModeCommand_t	  Cmd;
    _DevUartSetModeResponse_t     Rsp;
} _SlUartSetModeMsg_u;

#if _SL_INCLUDE_FUNC(sl_UartSetMode)
const _SlCmdCtrl_t _SlUartSetModeCmdCtrl = {
    SL_OPCODE_DEVICE_SETUARTMODECOMMAND,
    sizeof(_DevUartSetModeCommand_t),
    sizeof(_DevUartSetModeResponse_t)
};

int16_t cc3100::sl_UartSetMode(const SlUartIfParams_t* pUartParams)
{
    _SlUartSetModeMsg_u Msg;
    uint32_t magicCode = 0xFFFFFFFF;

    Msg.Cmd.BaudRate = pUartParams->BaudRate;
    Msg.Cmd.FlowControlEnable = pUartParams->FlowControlEnable;


    VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlUartSetModeCmdCtrl, &Msg, NULL));

    /* cmd response OK, we can continue with the handshake */
    if (SL_RET_CODE_OK == Msg.Rsp.status) {
        sl_IfMaskIntHdlr();

        /* Close the comm port */
        sl_IfClose(g_pCB->FD);

        /* Re-open the comm port */
        sl_IfOpen((void * )pUartParams, UART_IF_OPEN_FLAG_RE_OPEN);
        sl_IfUnMaskIntHdlr();

        /* send the magic code and wait for the response */
        sl_IfWrite(g_pCB->FD, (uint8_t* )&magicCode, 4);

        magicCode = UART_SET_MODE_MAGIC_CODE;
        sl_IfWrite(g_pCB->FD, (uint8_t* )&magicCode, 4);

        /* clear magic code */
        magicCode = 0;

        /* wait (blocking) till the magic code to be returned from device */
        sl_IfRead(g_pCB->FD, (uint8_t* )&magicCode, 4);

        /* check for the received magic code matching */
        if (UART_SET_MODE_MAGIC_CODE != magicCode) {
            _SL_ASSERT(0);
        }
    }

    return (int16_t)Msg.Rsp.status;
}
#endif
#endif

}//namespace