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: internal/wiconnect/ProcessCommand.cpp
- Revision:
- 0:ea85c4bb5e1f
- Child:
- 1:6ec9998427ad
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/internal/wiconnect/ProcessCommand.cpp Mon Aug 11 09:58:24 2014 +0000 @@ -0,0 +1,319 @@ +/* + * Copyright 2014, ACKme Networks + * All Rights Reserved. + * + * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks; + * the contents of this file may not be disclosed to third parties, copied + * or duplicated in any form, in whole or in part, without the prior + * written permission of ACKme Networks. + */ + + +#include "CommandCommon.h" + + + +/*************************************************************************************************/ +WiconnectResult Wiconnect::checkCurrentCommand() +{ + WiconnectResult result; + + start: + CHECK_INITIALIZED(); + if(!commandExecuting) + { + return WICONNECT_IDLE; + } + + CommandContext *context = (CommandContext*)commandContext; + + if(context->commandLen > 0) + { + const int timeout = context->nonBlocking ? 0 : timeoutTimer.remainingMs(context->timeoutMs); + const int bytesToWrite = context->commandLen; + const int bytesWritten = serial.write(context->commandPtr, bytesToWrite, timeout); + context->commandPtr += bytesWritten; + context->commandLen -= bytesWritten; + if(bytesToWrite != bytesWritten) + { + if(timeoutTimer.timedOut(context->timeoutMs)) + { + issueCommandCallback(WICONNECT_TIMEOUT); + return WICONNECT_TIMEOUT; + } + else + { + return WICONNECT_PROCESSING; + } + } + } + + while(context->reader.isValid()) + { + if(context->bytesToWrite == 0) + { + context->responseBufferPtr = context->responseBuffer; + if(WICONNECT_FAILED(result, context->reader.call(context->user, context->responseBuffer, context->responseBufferLen, &context->bytesToWrite))) + { + issueCommandCallback(result); + return result; + } + else if(context->bytesToWrite == EOF) + { + context->reader.setInvalid(); + context->bytesToWrite = 0; + context->responseBufferPtr = context->responseBuffer; + break; + } + else + { + timeoutTimer.reset(); + } + } + if(context->bytesToWrite > 0) + { + const int timeout = context->nonBlocking ? 0 : timeoutTimer.remainingMs(context->timeoutMs); + const int bytesToWrite = context->bytesToWrite; + const int bytesWritten = serial.write(context->responseBufferPtr, bytesToWrite, timeout); + context->responseBufferPtr += bytesWritten; + context->bytesToWrite -= bytesWritten; + if(bytesToWrite != bytesWritten) + { + if(timeoutTimer.timedOut(context->timeoutMs)) + { + issueCommandCallback(WICONNECT_TIMEOUT); + return WICONNECT_TIMEOUT; + } + else + { + return WICONNECT_PROCESSING; + } + } + } + } + + result = receiveResponse(); + if(result == WICONNECT_PROCESSING && !context->nonBlocking) + { + goto start; + } + return result; +} + +/*************************************************************************************************/ +WiconnectResult Wiconnect::receiveResponse() +{ + for(;;) + { + WiconnectResult result = receivePacket(); + + if(result == WICONNECT_PROCESSING) + { + return WICONNECT_PROCESSING; + } + else if(result == WICONNECT_SUCCESS) + { + CommandHeader *header = (CommandHeader*)commandHeaderBuffer; + CommandContext *context = (CommandContext*)commandContext; + + // TODO: need to notify safemode + + if(header->response_type == WICONNECT_CMD_TYPE_REPLY || header->response_type == WICONNECT_CMD_TYPE_SAFEMODE) + { + if(header->response_code != WICONNECT_CMD_SUCCESS) + { + DEBUG_CMD_ERROR(header->response_code); + flush(); + issueCommandCallback(WICONNECT_CMD_RESPONSE_ERROR); + return WICONNECT_CMD_RESPONSE_ERROR; + } + else if(header->response_len > 0) + { + DEBUG_CMD_RESPONSE(context->responseBuffer); + header->response_len -= 2; + context->responseBuffer[header->response_len] = 0; + } + else + { + *context->responseBuffer = 0; + } + + issueCommandCallback(WICONNECT_SUCCESS); + + return WICONNECT_SUCCESS; + } + else + { + DEBUG_CMD_LOG(context->responseBuffer); + RESET_CMD_HEADER(header); + context->responseBufferPtr = context->responseBuffer; + } + } + else + { + issueCommandCallback(result); + return result; + } + } + + // shouldn't get here... + return WICONNECT_ERROR; +} + +/*************************************************************************************************/ +WiconnectResult Wiconnect::receivePacket() +{ + CommandHeader *header = (CommandHeader*)commandHeaderBuffer; + CommandContext *context = (CommandContext*)commandContext; + + if(header->bytes_remaining > 0) + { + uint16_t bytesReceived; + uint8_t buffer[WICONNECT_HEADER_LENGTH]; + + while(header->bytes_remaining > 0) + { + const int timeout = context->nonBlocking ? 0 : timeoutTimer.remainingMs(context->timeoutMs); + bytesReceived = serial.read((char*)buffer, header->bytes_remaining, timeout); + if(bytesReceived == 0) + { + return timeoutTimer.timedOut(context->timeoutMs) ? WICONNECT_TIMEOUT : WICONNECT_PROCESSING; + } + + for(uint8_t *ptr = buffer; bytesReceived > 0; ++ptr) + { + if(header->response_type == WICONNECT_CMD_TYPE_NULL) + { + if( *ptr == WICONNECT_CMD_TYPE_REPLY || + *ptr == WICONNECT_CMD_TYPE_LOG || + *ptr == WICONNECT_CMD_TYPE_SAFEMODE) + { + header->response_type = (ResponseType)*ptr; + -- header->bytes_remaining; + } + --bytesReceived; + } + else if(header->response_code == WICONNECT_CMD_CODE_NULL) + { + if(*ptr >= '0' && *ptr <= '7') + { + header->response_code = (ResponseCode)(*ptr - '0' + 1); + --header->bytes_remaining; + header->len_buffer_ptr = header->len_buffer; + } + else + { + RESET_CMD_HEADER(header); + } + --bytesReceived; + } + else if(header->bytes_remaining > 2) + { + uint8_t len_chars = MIN((int)bytesReceived, (int)(header->bytes_remaining-2)); + header->bytes_remaining -= len_chars; + bytesReceived -= len_chars; + while(len_chars-- > 0) + { + *header->len_buffer_ptr++ = *ptr++; + } + --ptr; // need to decrement since the for loop increments + if(header->bytes_remaining == 2) + { + uint32_t packetLen; + *header->len_buffer_ptr = 0; + if(!StringUtil::strToUint32((const char*)header->len_buffer, &packetLen)) + { + RESET_CMD_HEADER(header); + } + else + { + if((int)packetLen > context->responseBufferLen) + { + DEBUG_ERROR("Packet larger than response buffer: %d > %d", packetLen, context->responseBufferLen); + return WICONNECT_OVERFLOW; + } + header->response_len = (uint16_t)packetLen; + context->bytesToRead = packetLen; + } + } + } + else if(header->bytes_remaining == 2) + { + --bytesReceived; + if(*ptr == '\r') + { + header->bytes_remaining = 1; + } + else + { + RESET_CMD_HEADER(header); + } + } + else + { + --bytesReceived; + if(*ptr == '\n') + { + header->bytes_remaining = 0; + break; + } + else + { + RESET_CMD_HEADER(header); + } + } + } + } + } + + while(context->bytesToRead > 0) + { + const int timeout = context->nonBlocking ? 0 : timeoutTimer.remainingMs(context->timeoutMs); + const int bytesToRead = context->bytesToRead; + const int bytesReceived = serial.read(context->responseBufferPtr, bytesToRead, timeout); + context->responseBufferPtr += bytesReceived; + context->bytesToRead -= bytesReceived; + + if(bytesReceived != bytesToRead) + { + return timeoutTimer.timedOut(context->timeoutMs) ? WICONNECT_TIMEOUT : WICONNECT_PROCESSING; + } + else if(context->bytesToRead == 0) + { + *context->responseBufferPtr = 0; + } + } + + return (header->response_code != WICONNECT_CMD_CODE_NULL && + header->response_type != WICONNECT_CMD_TYPE_NULL && + context->bytesToRead == 0) ? WICONNECT_SUCCESS : WICONNECT_PROCESSING; +} + +/*************************************************************************************************/ +void Wiconnect::issueCommandCallback(WiconnectResult result) +{ + CommandHeader *header = (CommandHeader*)commandHeaderBuffer; + CommandContext *context = (CommandContext*)commandContext; +#ifdef WICONNECT_ASYNC_TIMER_ENABLED + void *returnPtr = (currentQueuedCommand != NULL) ? (void*)currentQueuedCommand : (void*)context->responseBuffer; + currentQueuedCommand = NULL; + commandProcessorTimer.stop(); +#else + void *returnPtr = (void*)context->responseBuffer; +#endif + context->callback.call(result, returnPtr, (void*)(uint32_t)header->response_len); + commandExecuting = false; + +#ifdef WICONNECT_ASYNC_TIMER_ENABLED + processNextQueuedCommand(); +#endif +} + +/*************************************************************************************************/ +void Wiconnect::stopCurrentCommand() +{ + internalProcessingState = 0; + issueCommandCallback(WICONNECT_ABORTED); +} + +