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

Revision:
29:b6af04b77a56
--- /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;
+}