Driver for CC3000 Wi-Fi module

Dependencies:   NVIC_set_all_priorities

Dependents:   CC3000_Simple_Socket Wi-Go_IOT_Demo

Information

The current code has been reworked to a full object oriented application and contains an mbed socket compatible API.

CC3000 Wi-Fi module library

Info

This is the low level driver for TI's SimpleLink CC3000 device.
Port from Avnet's Wi-Go KEIL code (based on TI's CC3000 code).
Special thanks to Jim Carver from Avnet for providing the Wi-Go board and for his assistance.

Differences with TI's original code

The code functionality stays exactly the same.
In order to make it easier to use the code, following changes were made :

  • Addition of a tool to shift all IRQ priorities to a lower level since it is very important to keep the SPI handler at the highest system priority, the WLAN interrupt the second highest and all other system interrupts at a lower priority, so their handlers can be preempted by the CC3000 interrupts.
  • Addition of low level I/O controls and conditional compiler controls in cc3000_common.h.
  • CC3000 initialisation, pin declarations, SPI and WLAN irq priorities are set in Init_HostDriver , we need to call this function at the start of the main function.
  • The SPI and HCI code are joined into one file.
  • The include list has been rearranged - Only #include "wlan.h" is needed in the user API.
  • Part of the CC3000's user eeprom memory is used to store additional info (52 bytes in NVMEM_USER_FILE_1):
# bytesDescriptionInfo
1First time config parameterUseful when connecting
2Firmware updater versionused with the Firmware update tool
2Service Pack versionused with the Firmware update tool
3Driver Versionused with the Firmware update tool
3Firmware Versionused with the Firmware update tool
1CIK validation (Client Interface Key)
40CIK data (Client Interface Key)used with the exosite

Using the Library

A user API is needed to access the CC3000 functions.
Examples:

Using the library with other processors

cc3000_common.cpp loads the irq tool for all targets:
All current mbed targets are supported by this library.

#include "NVIC_set_all_priorities.h"


All low level settings that need to change are available in cc3000_common.h

//*****************************************************************************
//              PIN CONTROLS & COMPILE CONTROLS
//*****************************************************************************
// Compiler control
#define CC3000_UNENCRYPTED_SMART_CONFIG   // No encryption
//#define CC3000_TINY_DRIVER                // Driver for small memory model CPUs

//Interrupt controls
#define NVIC_ALL_IRQ        NVIC_set_all_irq_priorities(3);         // Set ALL interrupt priorities to level 3
#define NVIC_SPI_IRQ        NVIC_SetPriority(SPI0_IRQn, 0x0);       // Wi-Fi SPI interrupt must be higher priority than SysTick
#define NVIC_PORT_IRQ       NVIC_SetPriority(PORTA_IRQn, 0x1);
#define NVIC_SYSTICK_IRQ    NVIC_SetPriority(SysTick_IRQn, 0x2);    // SysTick set to lower priority than Wi-Fi SPI bus interrupt
//#define NVIC_ADC_IRQ        NVIC_SetPriority(ADC0_IRQn, 0x3);       // ADC is the lowest of all

// Wlan controls
#define WLAN_ISF_PCR        PORTA->PCR[16]
#define WLAN_ISF_ISFR       PORTA->ISFR
#define WLAN_ISF_MASK       (1<<16)

#define WLAN_ASSERT_CS      wlan_cs = 0;   //CS : active low
#define WLAN_DEASSERT_CS    wlan_cs = 1;

#define WLAN_ASSERT_EN      wlan_en = 1;   //EN : active high
#define WLAN_DEASSERT_EN    wlan_en = 0;

#define WLAN_READ_IRQ       wlan_int

#define WLAN_ENABLE_IRQ     wlan_int.fall(&WLAN_IRQHandler);
#define WLAN_DISABLE_IRQ    wlan_int.fall(NULL);

#define WLAN_IRQ_PIN_CREATE         InterruptIn wlan_int (PTA16);
#define WLAN_EN_PIN_CREATE          DigitalOut  wlan_en  (PTA13);
#define WLAN_CS_PIN_CREATE          DigitalOut  wlan_cs  (PTD0);
#define WLAN_SPI_PORT_CREATE        SPI wlan(PTD2, PTD3, PTC5); // mosi, miso, sclk

#define WLAN_SPI_PORT_INIT          wlan.format(8,1);
#define WLAN_SPI_SET_FREQ           wlan.frequency(12000000);
#define WLAN_SPI_SET_IRQ_HANDLER    wlan_int.fall(&WLAN_IRQHandler);

#define WLAN_SPI_WRITE              wlan.write(*data++);
#define WLAN_SPI_READ               wlan.write(0x03);          // !! DO NOT MODIFY the 0x03 parameter (CC3000 will not respond).

API documentation

Due to a little problem with the links on the mbed site, the API documentation is not directly accessible (will be solved in a next release).
Currently, it is only accessible by adding modules.html to the API doc link: http://mbed.org/users/frankvnk/code/CC3000_Hostdriver/docs/tip/modules.html

Revision:
0:c44f0314d6ec
Child:
1:bbcaf0b2f367
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wlan.cpp	Fri Jun 28 17:48:37 2013 +0000
@@ -0,0 +1,1240 @@
+/*****************************************************************************
+*
+*  wlan.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 wlan_api
+//! @{
+//
+//*****************************************************************************
+#include "wlan.h"
+
+extern int sss;
+extern void WriteWlanPin( unsigned char val );
+volatile sSimplLinkInformation tSLInformation;
+
+#define SMART_CONFIG_PROFILE_SIZE        67        // 67 = 32 (max ssid) + 32 (max key) + 1 (SSID length) + 1 (security type) + 1 (key length)
+
+#ifndef CC3000_UNENCRYPTED_SMART_CONFIG
+unsigned char key[AES128_KEY_SIZE];    
+unsigned char profileArray[SMART_CONFIG_PROFILE_SIZE];
+#endif //CC3000_UNENCRYPTED_SMART_CONFIG
+
+/* patches type */
+#define PATCHES_HOST_TYPE_WLAN_DRIVER   0x01
+#define PATCHES_HOST_TYPE_WLAN_FW       0x02
+#define PATCHES_HOST_TYPE_BOOTLOADER    0x03
+
+#define SL_SET_SCAN_PARAMS_INTERVAL_LIST_SIZE    (16)
+#define SL_SIMPLE_CONFIG_PREFIX_LENGTH           (3)
+#define ETH_ALEN                                 (6)
+#define MAXIMAL_SSID_LENGTH                      (32)
+
+#define SL_PATCHES_REQUEST_DEFAULT               (0)
+#define SL_PATCHES_REQUEST_FORCE_HOST            (1)
+#define SL_PATCHES_REQUEST_FORCE_NONE            (2)
+
+
+#define      WLAN_SEC_UNSEC  (0)
+#define      WLAN_SEC_WEP    (1)
+#define      WLAN_SEC_WPA    (2)
+#define      WLAN_SEC_WPA2   (3)
+
+
+#define WLAN_SL_INIT_START_PARAMS_LEN           (1)
+#define WLAN_PATCH_PARAMS_LENGTH                (8)
+#define WLAN_SET_CONNECTION_POLICY_PARAMS_LEN   (12)
+#define WLAN_DEL_PROFILE_PARAMS_LEN             (4)
+#define WLAN_SET_MASK_PARAMS_LEN                (4)
+#define WLAN_SET_SCAN_PARAMS_LEN                (100)
+#define WLAN_GET_SCAN_RESULTS_PARAMS_LEN        (4)
+#define WLAN_ADD_PROFILE_NOSEC_PARAM_LEN        (24)            
+#define WLAN_ADD_PROFILE_WEP_PARAM_LEN          (36)
+#define WLAN_ADD_PROFILE_WPA_PARAM_LEN          (44)
+#define WLAN_CONNECT_PARAM_LEN                  (29)
+#define WLAN_SMART_CONFIG_START_PARAMS_LEN      (4)
+
+
+
+
+//*****************************************************************************
+//
+//!  SimpleLink_Init_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    Send HCI_CMND_SIMPLE_LINK_START to CC3000
+//
+//*****************************************************************************
+static void SimpleLink_Init_Start(unsigned short usPatchesAvailableAtHost)
+{
+    unsigned char *ptr;
+    unsigned char *args;
+    
+    ptr = tSLInformation.pucTxCommandBuffer;
+    args = (unsigned char *)(ptr + HEADERS_SIZE_CMD);
+    
+    UINT8_TO_STREAM(args, ((usPatchesAvailableAtHost) ? SL_PATCHES_REQUEST_FORCE_HOST : SL_PATCHES_REQUEST_DEFAULT));
+    
+    // IRQ Line asserted - send HCI_CMND_SIMPLE_LINK_START to CC3000
+    hci_command_send(HCI_CMND_SIMPLE_LINK_START, ptr, WLAN_SL_INIT_START_PARAMS_LEN);
+    
+    SimpleLinkWaitEvent(HCI_CMND_SIMPLE_LINK_START, 0);
+}
+
+
+
+//*****************************************************************************
+//
+//!  wlan_init
+//!
+//!  @param  sWlanCB   Asynchronous events callback.  
+//!                    0 no event call back.
+//!                  -call back parameters:
+//!                   1) event_type: HCI_EVNT_WLAN_UNSOL_CONNECT connect event,
+//!                     HCI_EVNT_WLAN_UNSOL_DISCONNECT disconnect event,
+//!                     HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE config done,
+//!                     HCI_EVNT_WLAN_UNSOL_DHCP dhcp report, 
+//!                     HCI_EVNT_WLAN_ASYNC_PING_REPORT ping report OR 
+//!                     HCI_EVNT_WLAN_KEEPALIVE keepalive.
+//!                   2) data: pointer to extra data that received by the event
+//!                     (NULL no data).
+//!                   3) length: data length.
+//!                  -Events with extra data:
+//!                     HCI_EVNT_WLAN_UNSOL_DHCP: 4 bytes IP, 4 bytes Mask, 
+//!                     4 bytes default gateway, 4 bytes DHCP server and 4 bytes
+//!                     for DNS server.
+//!                     HCI_EVNT_WLAN_ASYNC_PING_REPORT: 4 bytes Packets sent, 
+//!                     4 bytes Packets received, 4 bytes Min round time, 
+//!                     4 bytes Max round time and 4 bytes for Avg round time.
+//!
+//!  @param    sFWPatches  0 no patch or pointer to FW patches 
+//!  @param    sDriverPatches  0 no patch or pointer to driver patches
+//!  @param    sBootLoaderPatches  0 no patch or pointer to bootloader patches
+//!  @param    sReadWlanInterruptPin    init callback. the callback read wlan 
+//!            interrupt status.
+//!  @param    sWlanInterruptEnable   init callback. the callback enable wlan 
+//!            interrupt.
+//!  @param    sWlanInterruptDisable   init callback. the callback disable wlan
+//!            interrupt.
+//!  @param    sWriteWlanPin      init callback. the callback write value 
+//!            to device pin.  
+//!
+//!  @return   none
+//!
+//!  @sa       wlan_set_event_mask , wlan_start , wlan_stop 
+//!
+//!  @brief    Initialize wlan driver
+//!
+//!  @warning This function must be called before ANY other wlan driver function
+//
+//*****************************************************************************
+
+void wlan_init(tWlanCB               sWlanCB,
+               tFWPatches            sFWPatches,
+               tDriverPatches        sDriverPatches,
+               tBootLoaderPatches    sBootLoaderPatches,
+               tWlanReadInteruptPin  sReadWlanInterruptPin,
+               tWlanInterruptEnable  sWlanInterruptEnable,
+               tWlanInterruptDisable sWlanInterruptDisable,
+               tWriteWlanPin         sWriteWlanPin)
+{
+    
+    tSLInformation.sFWPatches = sFWPatches;
+    tSLInformation.sDriverPatches = sDriverPatches;
+    tSLInformation.sBootLoaderPatches = sBootLoaderPatches;
+    
+    // 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();
+}
+
+//wait until the IRQ line goes low
+void do_lan_wait(void)
+{
+    int t;
+    t = sss + 3;
+    while(tSLInformation.ReadWlanInterruptPin() != 0)
+        {
+            if(t <= sss)
+            {
+                WriteWlanPin(0);
+                t = sss + 3;
+                while(sss < t);
+                WriteWlanPin(1);
+                t = sss + 3;
+                //printf("Retry %x\n", ReadWlanInterruptPin());
+            }
+            
+        }
+    }
+
+//*****************************************************************************
+//
+//!  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
+//!
+//
+//*****************************************************************************
+
+void wlan_start(unsigned short usPatchesAvailableAtHost)
+{
+    
+    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
+        do_lan_wait();
+    }
+    else
+    {
+        // wait till the IRQ line goes high and than 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
+//
+//*****************************************************************************
+
+void wlan_stop(void)
+{
+    // 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
+long wlan_connect(unsigned long ulSecType,
+                  char *ssid,
+                  long ssid_len,
+                  unsigned char *bssid,
+                  unsigned char *key,
+                  long key_len)
+{
+    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
+long wlan_connect(char *ssid, long ssid_len)
+{
+    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
+//
+//*****************************************************************************
+
+long wlan_disconnect()
+{
+    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 
+//
+//*****************************************************************************
+
+long wlan_ioctl_set_connection_policy(unsigned long should_connect_to_open_ap, 
+                                      unsigned long ulShouldUseFastConnect,
+                                      unsigned long ulUseProfiles)
+{
+    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.
+//!  @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, zero 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
+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)
+{
+    unsigned short arg_len = 0x00;
+    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;
+    }    
+    
+    // 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
+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)
+{
+    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 
+//
+//*****************************************************************************
+
+long wlan_ioctl_del_profile(unsigned long ulIndex)
+{
+    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
+long wlan_ioctl_get_scan_results(unsigned long ulScanTimeout,
+                                 unsigned char *ucResults)
+{
+    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
+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)
+{
+    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. 
+//
+//*****************************************************************************
+
+long wlan_set_event_mask(unsigned long ulMask)
+{
+    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
+long wlan_ioctl_statusget(void)
+{
+    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
+//
+//*****************************************************************************
+
+long wlan_smart_config_start(unsigned long algoEncryptedFlag)
+{
+    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
+//
+//*****************************************************************************
+
+long wlan_smart_config_stop(void)
+{
+    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
+//
+//*****************************************************************************
+
+long wlan_smart_config_set_prefix(char* cNewPrefix)
+{
+    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 CC3000_UNENCRYPTED_SMART_CONFIG
+long wlan_smart_config_process()
+{
+    signed long    returnValue;
+    unsigned long ssidLen, keyLen;
+    unsigned char *decKeyPtr;
+    unsigned char *ssidPtr;
+    
+    // read the key from EEPROM - fileID 12
+    returnValue = 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 = 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];
+    
+    aes_decrypt(decKeyPtr, key);
+    if (profileArray[profileArray[0] + 1] > 16)
+        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 = 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 = 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 = wlan_add_profile(WLAN_SEC_WPA2,     // security type
+                                           ssidPtr,
+                                           ssidLen,
+                                           NULL,              // BSSID
+                                           1,                 // Priority
+                                           0x18,              // PairwiseCipher
+                                           0x1e,              // GroupCipher
+                                           2,                 // KEY management
+                                           decKeyPtr,         // KEY
+                                           keyLen);           // KEY length
+            
+            break;
+        }
+    }
+    
+    return returnValue;
+}
+#endif //CC3000_UNENCRYPTED_SMART_CONFIG        
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************
+
+