Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Diff: simplelink/cc3100.cpp
- Revision:
- 0:e89ba455dbcf
- Child:
- 2:b3fd5b3d9860
diff -r 000000000000 -r e89ba455dbcf simplelink/cc3100.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/simplelink/cc3100.cpp Tue Feb 10 12:09:29 2015 +0000
@@ -0,0 +1,1378 @@
+/*
+* 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 "GetSNTPTime.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;
+
+
+cc3100::cc3100(PinName cc3100_irq, PinName cc3100_nHIB, PinName cc3100_cs, SPI cc3100_spi)
+ : _spi(cc3100_irq, cc3100_nHIB, cc3100_cs, cc3100_spi, _driver),
+ _driver(_nonos, _netapp, _flowcont, _spi), _nonos(_driver), _wlan(_driver, _wlan_filters),
+ _wlan_filters(_driver), _netapp(_driver, _nonos), _fs(_driver), _netcfg(_driver),
+ _socket(_driver, _nonos), _flowcont(_driver, _nonos)
+
+
+{
+
+}
+
+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;
+}
+
+int32_t cc3100::NetAppPingStart(SlPingStartCommand_t* pPingParams, uint8_t family, SlPingReport_t *pReport, const P_SL_DEV_PING_CALLBACK pPingCallback){
+
+ return (_netapp.sl_NetAppPingStart(pPingParams, family, pReport, pPingCallback));
+
+}
+
+int32_t cc3100::NetAppSet(uint8_t AppId ,uint8_t Option,uint8_t OptionLen, uint8_t *pOptionValue){
+
+ return (_netapp.sl_NetAppSet(AppId ,Option, OptionLen, (uint8_t *)pOptionValue));
+
+}
+
+int16_t cc3100::NetCfgSet(uint8_t ConfigId ,uint8_t ConfigOpt, uint8_t ConfigLen, uint8_t *pValues){
+
+ return (_netcfg.sl_NetCfgSet(ConfigId ,ConfigOpt, ConfigLen, (uint8_t *)pValues));
+
+}
+
+int16_t cc3100::WlanSet(uint16_t ConfigId ,uint16_t ConfigOpt,uint16_t ConfigLen, uint8_t *pValues){
+
+ return (_wlan.sl_WlanSet(ConfigId, ConfigOpt, ConfigLen, (uint8_t*)pValues));
+
+}
+
+void cc3100::SlNonOsMainLoopTask(){
+
+ _nonos._SlNonOsMainLoopTask();
+
+}
+
+int16_t cc3100::WlanSetMode(const uint8_t mode){
+
+ return ( _wlan.sl_WlanSetMode(mode));
+}
+
+/*!
+ \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 */
+ while(IS_CONNECTED(g_Status,STATUS_BIT_CONNECTION)) { SlNonOsMainLoopTask(); }
+ }
+
+ 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
+*/
+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 */
+ while(!IS_IP_ACQUIRED(g_Status,STATUS_BIT_IP_ACQUIRED)) {
+ _nonos._SlNonOsMainLoopTask();
+ }
+ }
+
+ /* 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 */
+ while(IS_CONNECTED(g_Status,STATUS_BIT_CONNECTION)) {
+ SlNonOsMainLoopTask();
+ }
+ }
+
+ /* 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 )
+ {
+ printf("Error creating socket\n\r\n\r");
+ }
+
+ return sd;
+}
+
+int32_t cc3100::sock_Close(int16_t sd){
+
+ return _socket.sl_Close(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()
+{
+ //printf(" cc3100::establishConnectionWithAP \n\r");
+ 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 */
+ while((!IS_CONNECTED(g_Status,STATUS_BIT_CONNECTION)) || (!IS_IP_ACQUIRED(g_Status,STATUS_BIT_IP_ACQUIRED))) { _nonos._SlNonOsMainLoopTask(); }
+ 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 */
+ while(!IS_PING_DONE(g_Status,STATUS_BIT_PING_DONE)) { SlNonOsMainLoopTask(); }
+
+ 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 */
+ while(!IS_PING_DONE(g_Status,STATUS_BIT_PING_DONE)) { SlNonOsMainLoopTask(); }
+
+ if (0 == g_PingPacketsRecv)
+ {
+ /* Problem with internet connection*/
+ ASSERT_ON_ERROR(INTERNET_CONNECTION_FAILED);
+ }
+
+ /* Internet connection is successful */
+ return SUCCESS;
+}
+
+/*****************************************************************************/
+/* Internal functions */
+/*****************************************************************************/
+
+int16_t cc3100::_sl_GetStartResponseConvert(uint32_t Status)
+{
+
+ switch(Status) {
+ case INIT_STA_OK:
+ return ROLE_STA;
+ case INIT_STA_ERR:
+ return ROLE_STA_ERR;
+ case INIT_AP_OK:
+ return ROLE_AP;
+ case INIT_AP_ERR:
+ return ROLE_AP_ERR;
+ case INIT_P2P_OK:
+ return ROLE_P2P;
+ case INIT_P2P_ERR:
+ return ROLE_P2P_ERR;
+ default:
+ return (int16_t)Status;
+ }
+}
+
+/*****************************************************************************/
+/* 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;
+ status_variable &= ~((uint32_t)1L<<(bit));
+ g_Status = status_variable;
+}
+
+void cc3100::SET_STATUS_BIT(uint32_t status_variable, const uint32_t bit){
+
+ g_Status = status_variable;
+ status_variable |= ((uint32_t)1L<<(bit));
+ g_Status = status_variable;
+}
+
+/*****************************************************************************/
+/* sl_Task */
+/*****************************************************************************/
+#if _SL_INCLUDE_FUNC(sl_Task)
+void cc3100::sl_Task(void)
+{
+#ifdef _SlTaskEntry
+ _nonos._SlNonOsMainLoopTask;
+
+#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();
+
+ /* 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;
+ }
+ /* Use Obj to issue the command, if not available try later */
+ ObjIdx = _driver._SlDrvWaitForPoolObj(START_STOP_ID,SL_MAX_SOCKETS);
+ if (MAX_CONCURRENT_ACTIONS == ObjIdx)
+ {
+ printf("SL_POOL_IS_EMPTY\r\n");
+ return SL_POOL_IS_EMPTY;
+ }
+ OSI_RET_OK_CHECK(_nonos.sl_LockObjLock(&g_pCB->ProtectionLockObj, NON_OS_LOCK_OBJ_UNLOCK_VALUE, NON_OS_LOCK_OBJ_LOCK_VALUE, SL_OS_WAIT_FOREVER));
+ g_pCB->ObjPool[ObjIdx].pRespArgs = (uint8_t *)&AsyncRsp;
+ OSI_RET_OK_CHECK(_nonos.sl_LockObjUnlock(&g_pCB->ProtectionLockObj, NON_OS_LOCK_OBJ_UNLOCK_VALUE));
+
+ if( g_pCB->FD >= 0) {
+ _spi.CC3100_disable();
+
+ if(NULL != pInitCallBack) {
+ g_pCB->pInitCallback = pInitCallBack;
+ }
+ _spi.CC3100_enable();
+
+ if (NULL == pInitCallBack) {
+
+ OSI_RET_OK_CHECK(_nonos.sl_SyncObjWait(&g_pCB->ObjPool[ObjIdx].SyncObj, NON_OS_SYNC_OBJ_SIGNAL_VALUE, NON_OS_SYNC_OBJ_CLEAR_VALUE, SL_OS_WAIT_FOREVER));
+ /*release Pool Object*/
+ _driver._SlDrvReleasePoolObj(g_pCB->FunctionParams.AsyncExt.ActionIndex);
+ return _sl_GetStartResponseConvert(AsyncRsp.Status);
+ }
+ }
+
+ return (int16_t)g_pCB->FD;
+
+}
+#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);
+
+ OSI_RET_OK_CHECK(_nonos.sl_LockObjLock(&g_pCB->ProtectionLockObj, NON_OS_LOCK_OBJ_UNLOCK_VALUE, NON_OS_LOCK_OBJ_LOCK_VALUE, SL_OS_WAIT_FOREVER));
+
+ 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));
+ OSI_RET_OK_CHECK(_nonos.sl_SyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj, NON_OS_SYNC_OBJ_SIGNAL_VALUE));
+ }
+ OSI_RET_OK_CHECK(_nonos.sl_LockObjUnlock(&g_pCB->ProtectionLockObj, NON_OS_LOCK_OBJ_UNLOCK_VALUE));
+
+ 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(uint16_t timeout)
+{
+ int16_t RetVal=0;
+ _SlStopMsg_u Msg;
+ _BasicResponse_t AsyncRsp;
+ int16_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;
+ /* Use Obj to issue the command, if not available try later */
+ ObjIdx = _driver._SlDrvWaitForPoolObj(START_STOP_ID,SL_MAX_SOCKETS);
+ if (MAX_CONCURRENT_ACTIONS == ObjIdx) {
+ return SL_POOL_IS_EMPTY;
+ }
+ OSI_RET_OK_CHECK(_nonos.sl_LockObjLock(&g_pCB->ProtectionLockObj, NON_OS_LOCK_OBJ_UNLOCK_VALUE, NON_OS_LOCK_OBJ_LOCK_VALUE, SL_OS_WAIT_FOREVER));
+
+ g_pCB->ObjPool[ObjIdx].pRespArgs = (uint8_t *)&AsyncRsp;
+
+ OSI_RET_OK_CHECK(_nonos.sl_LockObjUnlock(&g_pCB->ProtectionLockObj, NON_OS_LOCK_OBJ_UNLOCK_VALUE));
+
+ VERIFY_RET_OK(_driver._SlDrvCmdOp((_SlCmdCtrl_t *)&_SlStopCmdCtrl, &Msg, NULL));
+
+ if(SL_OS_RET_CODE_OK == (int16_t)Msg.Rsp.status) {
+ OSI_RET_OK_CHECK(_nonos.sl_SyncObjWait(&g_pCB->ObjPool[ObjIdx].SyncObj, NON_OS_SYNC_OBJ_SIGNAL_VALUE, NON_OS_SYNC_OBJ_CLEAR_VALUE, SL_OS_WAIT_FOREVER));
+ 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;
+
+const _SlCmdCtrl_t _SlEventMaskSetCmdCtrl = {
+ SL_OPCODE_DEVICE_EVENTMASKSET,
+ sizeof(_DevMaskEventSetCommand_t),
+ sizeof(_BasicResponse_t)
+};
+
+#if _SL_INCLUDE_FUNC(sl_EventMaskSet)
+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;
+
+const _SlCmdCtrl_t _SlEventMaskGetCmdCtrl = {
+ SL_OPCODE_DEVICE_EVENTMASKGET,
+ sizeof(_DevMaskEventGetCommand_t),
+ sizeof(_DevMaskEventGetResponse_t)
+};
+
+#if _SL_INCLUDE_FUNC(sl_EventMaskGet)
+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;
+
+const _SlCmdCtrl_t _SlDeviceGetCmdCtrl = {
+ SL_OPCODE_DEVICE_DEVICEGET,
+ sizeof(_DeviceSetGet_t),
+ sizeof(_DeviceSetGet_t)
+};
+
+#if _SL_INCLUDE_FUNC(sl_DevGet)
+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 ) {
+ CmdExt.TxPayloadLen = 0;
+ CmdExt.RxPayloadLen = *pConfigLen;
+ CmdExt.pTxPayload = NULL;
+ CmdExt.pRxPayload = (uint8_t *)pValues;
+ CmdExt.ActualRxPayloadLen = 0;
+
+ 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;
+
+const _SlCmdCtrl_t _SlDeviceSetCmdCtrl = {
+ SL_OPCODE_DEVICE_DEVICESET,
+ sizeof(_DeviceSetGet_t),
+ sizeof(_BasicResponse_t)
+};
+
+#if _SL_INCLUDE_FUNC(sl_DevSet)
+int32_t cc3100::sl_DevSet(uint8_t DeviceSetId ,uint8_t Option,uint8_t ConfigLen, uint8_t *pValues)
+{
+ _SlDeviceMsgSet_u Msg;
+ _SlCmdExt_t CmdExt;
+
+ CmdExt.TxPayloadLen = (ConfigLen+3) & (~3);
+ CmdExt.RxPayloadLen = 0;
+ CmdExt.pTxPayload = (uint8_t *)pValues;
+ CmdExt.pRxPayload = NULL;
+
+
+ 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;
+
+const _SlCmdCtrl_t _SlUartSetModeCmdCtrl = {
+ SL_OPCODE_DEVICE_SETUARTMODECOMMAND,
+ sizeof(_DevUartSetModeCommand_t),
+ sizeof(_DevUartSetModeResponse_t)
+};
+
+
+#if _SL_INCLUDE_FUNC(sl_UartSetMode)
+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
+
+