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
WiconnectFile.cpp
- Committer:
- dan_ackme
- Date:
- 2014-10-27
- Revision:
- 29:b6af04b77a56
File content as of revision 29:b6af04b77a56:
/** * 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; }