Host library for controlling a WiConnect enabled Wi-Fi module.

Dependents:   wiconnect-ota_example wiconnect-web_setup_example wiconnect-test-console wiconnect-tcp_server_example ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers WiconnectFile.cpp Source File

WiconnectFile.cpp

00001 /**
00002  * ACKme WiConnect Host Library is licensed under the BSD licence: 
00003  * 
00004  * Copyright (c)2014 ACKme Networks.
00005  * All rights reserved. 
00006  * 
00007  * Redistribution and use in source and binary forms, with or without modification, 
00008  * are permitted provided that the following conditions are met: 
00009  * 
00010  * 1. Redistributions of source code must retain the above copyright notice, 
00011  * this list of conditions and the following disclaimer. 
00012  * 2. Redistributions in binary form must reproduce the above copyright notice, 
00013  * this list of conditions and the following disclaimer in the documentation 
00014  * and/or other materials provided with the distribution. 
00015  * 3. The name of the author may not be used to endorse or promote products 
00016  * derived from this software without specific prior written permission. 
00017  * 
00018  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS AND ANY EXPRESS OR IMPLIED 
00019  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
00020  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
00021  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
00022  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
00023  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
00026  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
00027  * OF SUCH DAMAGE.
00028  */
00029 
00030 #include "Wiconnect.h"
00031 #include "internal/common.h"
00032 
00033 #define CHECK_OPENED_FOR_READING() if(!readEnabled) return WICONNECT_NOT_OPENED_FOR_READING
00034 
00035 
00036 
00037 
00038 /*************************************************************************************************/
00039 WiconnectFile::WiconnectFile(int rxBufferLen, void *rxBuffer_)
00040 {
00041     wiconnect = Wiconnect::getInstance();
00042 
00043     memset(&rxBuffer, 0, sizeof(Buffer));
00044 
00045     rxBuffer.size = rxBufferLen - 4;
00046     rxBuffer.buffer = (uint8_t*)rxBuffer_;
00047 
00048     if(rxBuffer.size > 0)
00049     {
00050         if(rxBuffer_ == NULL)
00051         {
00052 #ifdef WICONNECT_ENABLE_MALLOC
00053             wiconnect_assert(wiconnect, "File(), malloc not defined", wiconnect->_malloc != NULL);
00054             rxBuffer.buffer = (uint8_t*)wiconnect->_malloc(rxBufferLen);
00055             wiconnect_assert(wiconnect, "File(), failed to malloc buffer", rxBuffer.buffer != NULL);
00056             rxBuffer.allocated = true;
00057 #else
00058             wiconnect_assert(wiconnect, "must specify buffer", 0);
00059 #endif
00060         }
00061         rxBuffer.size -= 4;
00062     }
00063 
00064     previous = next = NULL;
00065     handle = 0xff;
00066     readEnabled = false;
00067     *name = 0;
00068     size = 0;
00069     type = FILE_TYPE_UNKNOWN;
00070     version = 0;
00071     flags = FILE_FLAG_NONE;
00072 }
00073 
00074 /*************************************************************************************************/
00075 WiconnectFile::~WiconnectFile()
00076 {
00077     while(close() == WICONNECT_PROCESSING)
00078     {
00079     }
00080 
00081 #ifdef WICONNECT_ENABLE_MALLOC
00082     if(rxBuffer.allocated && rxBuffer.size > 0)
00083     {
00084         wiconnect_assert(wiconnect, "~File(), free not defined", wiconnect->_free != NULL);
00085         wiconnect->_free(rxBuffer.buffer);
00086     }
00087 #endif
00088 }
00089 
00090 /*************************************************************************************************/
00091 WiconnectResult WiconnectFile::openForRead(uint8_t handle_, const char *filename)
00092 {
00093     handle = handle_;
00094     readEnabled = true;
00095     strcpy(name, filename);
00096 
00097     return WICONNECT_SUCCESS;
00098 }
00099 
00100 /*************************************************************************************************/
00101 WiconnectResult WiconnectFile::initWithListing(const char *typeStr, const char *flagsStr, const char* sizeStr, const char *versionStr, const char *nameStr)
00102 {
00103     uint32_t tmp;
00104 
00105     if(!StringUtil::strHexToUint32(&typeStr[2], &tmp))
00106     {
00107         return WICONNECT_RESPONSE_PARSE_ERROR;
00108     }
00109     type = (FileType)tmp;
00110 
00111     if(!StringUtil::strHexToUint32(flagsStr, &tmp))
00112     {
00113         return WICONNECT_RESPONSE_PARSE_ERROR;
00114     }
00115     flags = (FileFlags)tmp;
00116 
00117     if(!StringUtil::strToUint32(sizeStr, &tmp))
00118     {
00119         return WICONNECT_RESPONSE_PARSE_ERROR;
00120     }
00121     size = (uint32_t)tmp;
00122 
00123     if(!FileInterface::fileVersionStrToInt(versionStr, &version))
00124     {
00125         return WICONNECT_RESPONSE_PARSE_ERROR;
00126     }
00127 
00128     strcpy(name, nameStr);
00129 
00130     return WICONNECT_SUCCESS;
00131 }
00132 
00133 #ifdef WICONNECT_ENABLE_MALLOC
00134 /*************************************************************************************************/
00135 void* WiconnectFile::operator new(size_t size)
00136 {
00137     Wiconnect *wiconnect = Wiconnect::getInstance();
00138     wiconnect_assert(wiconnect, "File:new, malloc not defined", wiconnect->_malloc != NULL);
00139     return Wiconnect::getInstance()->_malloc(size);
00140 }
00141 
00142 /*************************************************************************************************/
00143 void WiconnectFile::operator delete(void* ptr)
00144 {
00145     Wiconnect *wiconnect = Wiconnect::getInstance();
00146     wiconnect_assert(wiconnect, "File:delete, free not defined", wiconnect->_free != NULL);
00147     Wiconnect::getInstance()->_free(ptr);
00148 }
00149 #endif
00150 
00151 /*************************************************************************************************/
00152 WiconnectResult WiconnectFile::close()
00153 {
00154     WiconnectResult result;
00155     CHECK_OPENED_FOR_READING();
00156     CHECK_OTHER_COMMAND_EXECUTING();
00157 
00158     if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("close %d", handle)))
00159     {
00160         readEnabled = false;
00161     }
00162 
00163     CHECK_CLEANUP_COMMAND();
00164 
00165     return result;
00166 }
00167 
00168 /*************************************************************************************************/
00169 const char* WiconnectFile::getName() const
00170 {
00171     return name;
00172 }
00173 
00174 /*************************************************************************************************/
00175 uint32_t WiconnectFile::getSize() const
00176 {
00177     return size;
00178 }
00179 
00180 /*************************************************************************************************/
00181 FileType WiconnectFile::getType() const
00182 {
00183     return type;
00184 }
00185 
00186 /*************************************************************************************************/
00187 FileFlags WiconnectFile::getFlags() const
00188 {
00189     return flags;
00190 }
00191 
00192 /*************************************************************************************************/
00193 uint32_t WiconnectFile::getVersion() const
00194 {
00195     return version;
00196 }
00197 
00198 /*************************************************************************************************/
00199 const char* WiconnectFile::getVersionStr(char *buffer) const
00200 {
00201     return FileInterface::fileVersionIntToStr(version, true, buffer);
00202 }
00203 
00204 /*************************************************************************************************/
00205 const WiconnectFile* WiconnectFile::getNext() const
00206 {
00207     return next;
00208 }
00209 
00210 /*************************************************************************************************/
00211 const WiconnectFile* WiconnectFile::getPrevious() const
00212 {
00213     return previous;
00214 }
00215 
00216 
00217 /*************************************************************************************************/
00218 WiconnectResult WiconnectFile::read(void* buffer, uint16_t maxLength, uint16_t *bytesReadPtr)
00219 {
00220     WiconnectResult result;
00221 
00222     CHECK_OPENED_FOR_READING();
00223 
00224     if(rxBuffer.size > 0)
00225     {
00226         uint16_t bytesToRead = 0;
00227         const uint16_t bufferedBytes = (&rxBuffer.buffer[rxBuffer.bytesPending] - rxBuffer.ptr);
00228         if(bufferedBytes > 0)
00229         {
00230             bytesToRead = MIN(bufferedBytes, maxLength);
00231             memcpy(buffer, rxBuffer.ptr, bytesToRead);
00232             rxBuffer.ptr += bytesToRead;
00233             *bytesReadPtr = bytesToRead;
00234         }
00235         if(rxBuffer.ptr >= &rxBuffer.buffer[rxBuffer.bytesPending])
00236         {
00237             clearRxBuffer();
00238         }
00239         if(bytesToRead > 0)
00240         {
00241             return WICONNECT_SUCCESS;
00242         }
00243     }
00244 
00245     CHECK_OTHER_COMMAND_EXECUTING();
00246 
00247     if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand((char*)buffer, maxLength, "read %d %d", handle, maxLength)))
00248     {
00249         *bytesReadPtr = wiconnect->getLastCommandResponseLength();
00250     }
00251 
00252     CHECK_CLEANUP_COMMAND();
00253 
00254     return result;
00255 }
00256 
00257 /*************************************************************************************************/
00258 WiconnectResult WiconnectFile::read(uint8_t **bufferPtr, uint16_t *bytesReadPtr)
00259 {
00260     WiconnectResult result = WICONNECT_SUCCESS;
00261 
00262     CHECK_OPENED_FOR_READING();
00263 
00264     if(rxBuffer.size == 0)
00265     {
00266         return WICONNECT_UNSUPPORTED;
00267     }
00268     else if(bufferPtr != NULL && bytesReadPtr == NULL)
00269     {
00270         return WICONNECT_BAD_ARG;
00271     }
00272 
00273     if(rxBuffer.ptr >= &rxBuffer.buffer[rxBuffer.bytesPending])
00274     {
00275         clearRxBuffer();
00276     }
00277 
00278 
00279     if(rxBuffer.bytesPending < rxBuffer.size)
00280     {
00281         const int bytesToRead = rxBuffer.size - rxBuffer.bytesPending;
00282         char* ptr = (char*)&rxBuffer.buffer[rxBuffer.bytesPending];
00283 
00284         CHECK_OTHER_COMMAND_EXECUTING();
00285 
00286         loop:
00287         if(bytesToRead > 0 && WICONNECT_SUCCEEDED(result, wiconnect->sendCommand(ptr, bytesToRead, "read %d %d", handle, bytesToRead)))
00288         {
00289             const uint16_t bytesRead = wiconnect->getLastCommandResponseLength();
00290             rxBuffer.bytesPending += bytesRead;
00291         }
00292 
00293         // if still processing and in non-blocking mode,
00294         // then this api call must block until the command completes
00295         if(result == WICONNECT_PROCESSING && wiconnect->nonBlocking)
00296         {
00297             goto loop;
00298         }
00299 
00300         CHECK_CLEANUP_COMMAND();
00301     }
00302 
00303     if(bufferPtr != NULL)
00304     {
00305         *bufferPtr = rxBuffer.buffer;
00306         *bytesReadPtr = rxBuffer.bytesPending;
00307         clearRxBuffer();
00308     }
00309 
00310     return result;
00311 }
00312 
00313 /*************************************************************************************************/
00314 WiconnectResult WiconnectFile::getc(uint8_t *c)
00315 {
00316     WiconnectResult result;
00317 
00318     if(rxBuffer.size == 0)
00319     {
00320         return WICONNECT_UNSUPPORTED;
00321     }
00322 
00323     if(rxBuffer.bytesPending == 0 &&
00324       WICONNECT_FAILED(result, read()))
00325     {
00326         return result;
00327     }
00328     else if(rxBuffer.ptr < &rxBuffer.buffer[rxBuffer.bytesPending])
00329     {
00330         *c = *rxBuffer.ptr;
00331         ++rxBuffer.ptr;
00332         return WICONNECT_SUCCESS;
00333     }
00334     else
00335     {
00336         clearRxBuffer();
00337         return WICONNECT_ERROR;
00338     }
00339 }
00340 
00341 /*************************************************************************************************/
00342 void WiconnectFile::clearRxBuffer()
00343 {
00344     rxBuffer.bytesPending = 0;
00345     rxBuffer.ptr = rxBuffer.buffer;
00346 }