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
Diff: WiconnectFile.cpp
- Revision:
- 29:b6af04b77a56
diff -r 3c52f578708a -r b6af04b77a56 WiconnectFile.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WiconnectFile.cpp Mon Oct 27 13:42:26 2014 -0700 @@ -0,0 +1,346 @@ +/** + * ACKme WiConnect Host Library is licensed under the BSD licence: + * + * Copyright (c)2014 ACKme Networks. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "Wiconnect.h" +#include "internal/common.h" + +#define CHECK_OPENED_FOR_READING() if(!readEnabled) return WICONNECT_NOT_OPENED_FOR_READING + + + + +/*************************************************************************************************/ +WiconnectFile::WiconnectFile(int rxBufferLen, void *rxBuffer_) +{ + wiconnect = Wiconnect::getInstance(); + + memset(&rxBuffer, 0, sizeof(Buffer)); + + rxBuffer.size = rxBufferLen - 4; + rxBuffer.buffer = (uint8_t*)rxBuffer_; + + if(rxBuffer.size > 0) + { + if(rxBuffer_ == NULL) + { +#ifdef WICONNECT_ENABLE_MALLOC + wiconnect_assert(wiconnect, "File(), malloc not defined", wiconnect->_malloc != NULL); + rxBuffer.buffer = (uint8_t*)wiconnect->_malloc(rxBufferLen); + wiconnect_assert(wiconnect, "File(), failed to malloc buffer", rxBuffer.buffer != NULL); + rxBuffer.allocated = true; +#else + wiconnect_assert(wiconnect, "must specify buffer", 0); +#endif + } + rxBuffer.size -= 4; + } + + previous = next = NULL; + handle = 0xff; + readEnabled = false; + *name = 0; + size = 0; + type = FILE_TYPE_UNKNOWN; + version = 0; + flags = FILE_FLAG_NONE; +} + +/*************************************************************************************************/ +WiconnectFile::~WiconnectFile() +{ + while(close() == WICONNECT_PROCESSING) + { + } + +#ifdef WICONNECT_ENABLE_MALLOC + if(rxBuffer.allocated && rxBuffer.size > 0) + { + wiconnect_assert(wiconnect, "~File(), free not defined", wiconnect->_free != NULL); + wiconnect->_free(rxBuffer.buffer); + } +#endif +} + +/*************************************************************************************************/ +WiconnectResult WiconnectFile::openForRead(uint8_t handle_, const char *filename) +{ + handle = handle_; + readEnabled = true; + strcpy(name, filename); + + return WICONNECT_SUCCESS; +} + +/*************************************************************************************************/ +WiconnectResult WiconnectFile::initWithListing(const char *typeStr, const char *flagsStr, const char* sizeStr, const char *versionStr, const char *nameStr) +{ + uint32_t tmp; + + if(!StringUtil::strHexToUint32(&typeStr[2], &tmp)) + { + return WICONNECT_RESPONSE_PARSE_ERROR; + } + type = (FileType)tmp; + + if(!StringUtil::strHexToUint32(flagsStr, &tmp)) + { + return WICONNECT_RESPONSE_PARSE_ERROR; + } + flags = (FileFlags)tmp; + + if(!StringUtil::strToUint32(sizeStr, &tmp)) + { + return WICONNECT_RESPONSE_PARSE_ERROR; + } + size = (uint32_t)tmp; + + if(!FileInterface::fileVersionStrToInt(versionStr, &version)) + { + return WICONNECT_RESPONSE_PARSE_ERROR; + } + + strcpy(name, nameStr); + + return WICONNECT_SUCCESS; +} + +#ifdef WICONNECT_ENABLE_MALLOC +/*************************************************************************************************/ +void* WiconnectFile::operator new(size_t size) +{ + Wiconnect *wiconnect = Wiconnect::getInstance(); + wiconnect_assert(wiconnect, "File:new, malloc not defined", wiconnect->_malloc != NULL); + return Wiconnect::getInstance()->_malloc(size); +} + +/*************************************************************************************************/ +void WiconnectFile::operator delete(void* ptr) +{ + Wiconnect *wiconnect = Wiconnect::getInstance(); + wiconnect_assert(wiconnect, "File:delete, free not defined", wiconnect->_free != NULL); + Wiconnect::getInstance()->_free(ptr); +} +#endif + +/*************************************************************************************************/ +WiconnectResult WiconnectFile::close() +{ + WiconnectResult result; + CHECK_OPENED_FOR_READING(); + CHECK_OTHER_COMMAND_EXECUTING(); + + if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("close %d", handle))) + { + readEnabled = false; + } + + CHECK_CLEANUP_COMMAND(); + + return result; +} + +/*************************************************************************************************/ +const char* WiconnectFile::getName() const +{ + return name; +} + +/*************************************************************************************************/ +uint32_t WiconnectFile::getSize() const +{ + return size; +} + +/*************************************************************************************************/ +FileType WiconnectFile::getType() const +{ + return type; +} + +/*************************************************************************************************/ +FileFlags WiconnectFile::getFlags() const +{ + return flags; +} + +/*************************************************************************************************/ +uint32_t WiconnectFile::getVersion() const +{ + return version; +} + +/*************************************************************************************************/ +const char* WiconnectFile::getVersionStr(char *buffer) const +{ + return FileInterface::fileVersionIntToStr(version, true, buffer); +} + +/*************************************************************************************************/ +const WiconnectFile* WiconnectFile::getNext() const +{ + return next; +} + +/*************************************************************************************************/ +const WiconnectFile* WiconnectFile::getPrevious() const +{ + return previous; +} + + +/*************************************************************************************************/ +WiconnectResult WiconnectFile::read(void* buffer, uint16_t maxLength, uint16_t *bytesReadPtr) +{ + WiconnectResult result; + + CHECK_OPENED_FOR_READING(); + + if(rxBuffer.size > 0) + { + uint16_t bytesToRead = 0; + const uint16_t bufferedBytes = (&rxBuffer.buffer[rxBuffer.bytesPending] - rxBuffer.ptr); + if(bufferedBytes > 0) + { + bytesToRead = MIN(bufferedBytes, maxLength); + memcpy(buffer, rxBuffer.ptr, bytesToRead); + rxBuffer.ptr += bytesToRead; + *bytesReadPtr = bytesToRead; + } + if(rxBuffer.ptr >= &rxBuffer.buffer[rxBuffer.bytesPending]) + { + clearRxBuffer(); + } + if(bytesToRead > 0) + { + return WICONNECT_SUCCESS; + } + } + + CHECK_OTHER_COMMAND_EXECUTING(); + + if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand((char*)buffer, maxLength, "read %d %d", handle, maxLength))) + { + *bytesReadPtr = wiconnect->getLastCommandResponseLength(); + } + + CHECK_CLEANUP_COMMAND(); + + return result; +} + +/*************************************************************************************************/ +WiconnectResult WiconnectFile::read(uint8_t **bufferPtr, uint16_t *bytesReadPtr) +{ + WiconnectResult result = WICONNECT_SUCCESS; + + CHECK_OPENED_FOR_READING(); + + if(rxBuffer.size == 0) + { + return WICONNECT_UNSUPPORTED; + } + else if(bufferPtr != NULL && bytesReadPtr == NULL) + { + return WICONNECT_BAD_ARG; + } + + if(rxBuffer.ptr >= &rxBuffer.buffer[rxBuffer.bytesPending]) + { + clearRxBuffer(); + } + + + if(rxBuffer.bytesPending < rxBuffer.size) + { + const int bytesToRead = rxBuffer.size - rxBuffer.bytesPending; + char* ptr = (char*)&rxBuffer.buffer[rxBuffer.bytesPending]; + + CHECK_OTHER_COMMAND_EXECUTING(); + + loop: + if(bytesToRead > 0 && WICONNECT_SUCCEEDED(result, wiconnect->sendCommand(ptr, bytesToRead, "read %d %d", handle, bytesToRead))) + { + const uint16_t bytesRead = wiconnect->getLastCommandResponseLength(); + rxBuffer.bytesPending += bytesRead; + } + + // if still processing and in non-blocking mode, + // then this api call must block until the command completes + if(result == WICONNECT_PROCESSING && wiconnect->nonBlocking) + { + goto loop; + } + + CHECK_CLEANUP_COMMAND(); + } + + if(bufferPtr != NULL) + { + *bufferPtr = rxBuffer.buffer; + *bytesReadPtr = rxBuffer.bytesPending; + clearRxBuffer(); + } + + return result; +} + +/*************************************************************************************************/ +WiconnectResult WiconnectFile::getc(uint8_t *c) +{ + WiconnectResult result; + + if(rxBuffer.size == 0) + { + return WICONNECT_UNSUPPORTED; + } + + if(rxBuffer.bytesPending == 0 && + WICONNECT_FAILED(result, read())) + { + return result; + } + else if(rxBuffer.ptr < &rxBuffer.buffer[rxBuffer.bytesPending]) + { + *c = *rxBuffer.ptr; + ++rxBuffer.ptr; + return WICONNECT_SUCCESS; + } + else + { + clearRxBuffer(); + return WICONNECT_ERROR; + } +} + +/*************************************************************************************************/ +void WiconnectFile::clearRxBuffer() +{ + rxBuffer.bytesPending = 0; + rxBuffer.ptr = rxBuffer.buffer; +}