cc3100_Socket_Wifi_Server with Ethernet Interface not working
Dependencies: EthernetInterface mbed-rtos mbed
Fork of cc3100_Test_Demo by
simplelink/cc3100.cpp
- Committer:
- dflet
- Date:
- 2015-02-10
- Revision:
- 0:e89ba455dbcf
- Child:
- 2:b3fd5b3d9860
File content as of revision 0:e89ba455dbcf:
/* * 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