TI's CC3100 host driver and demo. Experimental and a work in progress.

Dependencies:   mbed

main.cpp

Committer:
dflet
Date:
2014-11-19
Revision:
2:a3e52cf86086
Parent:
1:da33a9116bda

File content as of revision 2:a3e52cf86086:

/*
 * main.c - sample application to switch to AP mode and ping client
 *
 * 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.
 *
 */

/*
 * Application Name     -   Getting started with Wi-Fi Access-Point mode
 * Application Overview -   This sample application demonstrates how
 *                          to configure CC3100 in Access-Point mode. Any
 *                          WLAN station in its range can connect/communicate
 *                          to/with it as per the standard networking protocols.
 *                          On a successful connection, the device ping's the
 *                          connected station.
 * Application Details  -   http://processors.wiki.ti.com/index.php/CC31xx_Getting_Started_with_WLAN_AP
 *                          doc\examples\getting_started_with_wlan_ap.pdf
 */

#include "mbed.h"
#include "cc3100_simplelink.h"
#include "cc3100_sl_common.h"
#include "BoardInit.h"

#if (THIS_BOARD == MBED_BOARD_LPC1768) 
Serial pc(USBTX, USBRX);//lpc1768
#elif (THIS_BOARD == ST_MBED_NUCLEOF411)
Serial pc(SERIAL_TX, SERIAL_RX);//nucleoF411
#elif (THIS_BOARD == EA_MBED_LPC4088)
Serial pc(USBTX, USBRX);
#elif (THIS_BOARD == ST_MBED_NUCLEOF103)
Serial pc(SERIAL_TX, SERIAL_RX);
#else

#endif

//using namespace mbed_cc3100;
 
#define APPLICATION_VERSION "1.1.0"

#define SL_STOP_TIMEOUT        0xFF

/* Use bit 32: Lower bits of status variable are used for NWP events
 *      1 in a 'status_variable', the device has completed the ping operation
 *      0 in a 'status_variable', the device has not completed the ping operation
 */
//#define STATUS_BIT_PING_DONE  31

#define CONFIG_IP       SL_IPV4_VAL(192,168,0,1)    /* Static IP to be configured */
#define CONFIG_MASK     SL_IPV4_VAL(255,255,255,0)  /* Subnet Mask for the station */
#define CONFIG_GATEWAY  SL_IPV4_VAL(192,168,0,1)    /* Default Gateway address */
#define CONFIG_DNS      SL_IPV4_VAL(192,168,0,1)    /* DNS Server Address */

#define DHCP_START_IP    SL_IPV4_VAL(192,168,0,100) /* DHCP start IP address */
#define DHCP_END_IP      SL_IPV4_VAL(192,168,0,200) /* DHCP End IP address */

#define IP_LEASE_TIME        3600

#define PING_INTERVAL        1000
#define PING_SIZE            20
#define PING_REQUEST_TIMEOUT 3000
#define PING_ATTEMPT         3

/* Application specific status/error codes */
typedef enum{
    LAN_CONNECTION_FAILED = -0x7D0,        /* Choosing this number to avoid overlap with host-driver's error codes */
    INTERNET_CONNECTION_FAILED = LAN_CONNECTION_FAILED - 1,
    DEVICE_NOT_IN_STATION_MODE = INTERNET_CONNECTION_FAILED - 1,

    STATUS_CODE_MAX = -0xBB8
}e_AppStatusCodes;
/*
#define IS_PING_DONE(status_variable)           GET_STATUS_BIT(status_variable, \
                                                               STATUS_BIT_PING_DONE)
*/
/*
 * GLOBAL VARIABLES -- Start
 */

//extern unsigned int  g_GatewayIP = 0;
//extern unsigned int  g_StationIP = 0;
unsigned int  g_PingPacketsRecv = 0;

/*
 * GLOBAL VARIABLES -- End
 */


/*
 * STATIC FUNCTION DEFINITIONS -- Start
 */
static signed int configureSimpleLinkToDefaultState();
static signed int initializeAppVariables();
static void displayBanner();

/*
 * STATIC FUNCTION DEFINITIONS -- End
 */

/*
 * ASYNCHRONOUS EVENT HANDLERS -- Start
 */

/*!
    \brief This function handles ping report events

    \param[in]      pPingReport holds the ping report statistics

    \return         None

    \note

    \warning
*/

static void SimpleLinkPingReport(SlPingReport_t *pPingReport)
{
    SET_STATUS_BIT(g_Status, STATUS_BIT_PING_DONE);

    if(pPingReport == NULL)

        printf(" [PING REPORT] NULL Pointer Error\r\n");

    g_PingPacketsRecv = pPingReport->PacketsReceived;
}

/*
 * ASYNCHRONOUS EVENT HANDLERS -- End
 */


/*
 * Application's entry point
 */
int main()
{
    pc.baud(115200);
    
    SlPingStartCommand_t PingParams = {0};
    SlPingReport_t Report = {0};
    SlNetCfgIpV4Args_t ipV4 = {0};
    SlNetAppDhcpServerBasicOpt_t dhcpParams = {0};

    unsigned char SecType = 0;
    signed int mode = ROLE_STA;
    signed int retVal = -1;

    retVal = initializeAppVariables();
    ASSERT_ON_ERROR(retVal);

    displayBanner();

    CLR_STATUS_BIT(g_Status, STATUS_BIT_PING_DONE);
    g_PingPacketsRecv = 0;

    /*
     * Following function configures 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
     */
    retVal = configureSimpleLinkToDefaultState();

    if(retVal < 0)
    {
        if (DEVICE_NOT_IN_STATION_MODE == retVal)
            printf(" Failed to configure the device in its default state \n\r");

        LOOP_FOREVER();
    }

    printf(" 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
     */
    mode = sl_Start(0, 0, 0);
    if (ROLE_AP == mode)
    {
        /* If the device is in AP mode, we need to wait for this event before doing anything */
        while(!IS_IP_ACQUIRED(g_Status)) { _SlNonOsMainLoopTask(); }
    }
    else
    {
        /* Configure CC3100 to start in AP mode */
        retVal = sl_WlanSetMode(ROLE_AP);
        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);

        mode = sl_Start(0, 0, 0);
        if (ROLE_AP == mode)
        {
            /* If the device is in AP mode, we need to wait for this event before doing anything */
            while(!IS_IP_ACQUIRED(g_Status)) { _SlNonOsMainLoopTask(); }
        }
        else
        {
            printf(" Device couldn't be configured in AP mode \n\r");
            LOOP_FOREVER();
        }
    }
    
    printf(" Ready to configue SSID\r\n");

    /* Configure the SSID of the CC3100 */
    retVal = sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_SSID,
            pal_Strlen(SSID_AP_MODE), (unsigned char *)SSID_AP_MODE);
    if(retVal < 0)
        LOOP_FOREVER();

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

    retVal = sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_PASSWORD, pal_Strlen(PASSWORD_AP_MODE),
            (unsigned char *)PASSWORD_AP_MODE);
    if(retVal < 0)
        LOOP_FOREVER();

    ipV4.ipV4 = CONFIG_IP;
    ipV4.ipV4Mask = CONFIG_MASK;
    ipV4.ipV4Gateway = CONFIG_GATEWAY;
    ipV4.ipV4DnsServer = CONFIG_DNS;

    /* Configure the Static IP */
    retVal = sl_NetCfgSet(SL_IPV4_AP_P2P_GO_STATIC_ENABLE,1,sizeof(SlNetCfgIpV4Args_t),
            (unsigned char *)&ipV4);
    if(retVal < 0)
        LOOP_FOREVER();

    dhcpParams.lease_time      = IP_LEASE_TIME;
    dhcpParams.ipv4_addr_start =  DHCP_START_IP;
    dhcpParams.ipv4_addr_last  =  DHCP_END_IP;

    retVal = sl_NetAppSet(SL_NET_APP_DHCP_SERVER_ID, NETAPP_SET_DHCP_SRV_BASIC_OPT,
            sizeof(SlNetAppDhcpServerBasicOpt_t), (unsigned char*)&dhcpParams);
    if(retVal < 0)
        LOOP_FOREVER();

    /* Restart the CC3100 */
    retVal = sl_Stop(SL_STOP_TIMEOUT);
    if(retVal < 0)
        LOOP_FOREVER();

    g_Status = 0;

    mode = sl_Start(0, 0, 0);
    if (ROLE_AP == mode)
    {
        /* If the device is in AP mode, we need to wait for this event before doing anything */
        while(!IS_IP_ACQUIRED(g_Status)) { _SlNonOsMainLoopTask(); }
    }
    else
    {
        printf(" Device couldn't come in AP mode \n\r");
        LOOP_FOREVER();
    }
    
    printf(" Device started as Access Point\n\r");

    /* Wait */
    printf(" Waiting for clients to connect...!\n\r");
    while((!IS_IP_LEASED(g_Status)) || (!IS_STA_CONNECTED(g_Status))) { _SlNonOsMainLoopTask(); }
    printf(" Client connected to the device \n\r");
    printf(" Pinging...! \n\r");

    /* Set the ping parameters */
    PingParams.PingIntervalTime = PING_INTERVAL;
    PingParams.PingSize = PING_SIZE;
    PingParams.PingRequestTimeout = PING_REQUEST_TIMEOUT;
    PingParams.TotalNumberOfAttempts = PING_ATTEMPT;
    PingParams.Flags = 0;
    PingParams.Ip = g_StationIP; /* Fill the station IP address connected to CC3100 */

    /* Ping client connected to CC3100 */
    retVal = sl_NetAppPingStart((SlPingStartCommand_t*)&PingParams, SL_AF_INET,
                       (SlPingReport_t*)&Report, SimpleLinkPingReport);
    if(retVal < 0)
        LOOP_FOREVER();

    /* Wait */
    while(!IS_PING_DONE(g_Status)) { _SlNonOsMainLoopTask(); }

    if (0 == g_PingPacketsRecv)
    {
        printf(" A STATION couldn't connect to the device \n\r");
        ASSERT_ON_ERROR(LAN_CONNECTION_FAILED);
    }

    printf(" Device and the station are successfully connected \n\r");
    return SUCCESS;
}


/*! 
    \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
*/
static signed int configureSimpleLinkToDefaultState()
{
    SlVersionFull   ver = {0};
    _WlanRxFilterOperationCommandBuff_t  RxFilterIdMask = {0};
    unsigned char           val = 1;
    unsigned char           configOpt = 0;
    unsigned char           configLen = 0;
    unsigned char           power = 0;

    signed int          retVal = -1;
    signed int          mode = -1;

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

    /* If the device is not in station-mode, try configuring it in station-mode */
    if (ROLE_STA != mode)
    {
        if (ROLE_AP == mode)
        {
            /* If the device is in AP mode, we need to wait for this event before doing anything */
            while(!IS_IP_ACQUIRED(g_Status)) { _SlNonOsMainLoopTask(); }
        }

        /* Switch to STA role and restart */
        retVal = 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, (unsigned char *)(&ver));
    ASSERT_ON_ERROR(retVal);

    /* Set connection policy to Auto + SmartConfig (Device's default connection policy) */
    retVal = sl_WlanPolicySet(SL_POLICY_CONNECTION, SL_CONNECTION_POLICY(1, 0, 0, 0, 1), NULL, 0);
    ASSERT_ON_ERROR(retVal);

    /* Remove all profiles */
    retVal = 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 = sl_WlanDisconnect();
    if(0 == retVal)
    {
        /* Wait */
        while(IS_CONNECTED(g_Status)) { _SlNonOsMainLoopTask(); }
    }

    /* Enable DHCP client*/
    retVal = sl_NetCfgSet(SL_IPV4_STA_P2P_CL_DHCP_ENABLE,1,1,&val);
    ASSERT_ON_ERROR(retVal);

    /* Disable scan */
    configOpt = SL_SCAN_POLICY(0);
    retVal = 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 = sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID, WLAN_GENERAL_PARAM_OPT_STA_TX_POWER, 1, (unsigned char *)&power);
    ASSERT_ON_ERROR(retVal);

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

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

    /* Remove  all 64 filters (8*8) */
    pal_Memset(RxFilterIdMask.FilterIdMask, 0xFF, 8);
    retVal = sl_WlanRxFilterSet(SL_REMOVE_RX_FILTER, (unsigned char *)&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 This function initializes the application variables

    \param[in]  None

    \return     0 on success, negative error-code on error
*/
static signed int initializeAppVariables()
{
    //g_Status = 0;
    //g_PingPacketsRecv = 0;
    //g_StationIP = 0;

    return SUCCESS;
}

/*!
    \brief This function displays the application's banner

    \param      None

    \return     None
*/
static void displayBanner()
{
    printf("\n\r\n\r");
    printf(" Getting started with WLAN access-point application - Version ");
    printf("%s",APPLICATION_VERSION);
    printf("\n\r*******************************************************************\n\r");
}