Vodafone K3770/K3772-Z modems driver & networking library
Dependencies: Socket USBHostWANDongle lwip-sys lwip
Dependents: VodafoneUSBModemHTTPClientTest VodafoneUSBModemNTPClientTest VodafoneUSBModemSMSTest VodafoneUSBModemUSSDTest ... more
Fork of VodafoneUSBModem_bleedingedge by
This is the driver for the Vodafone K3700 & K3772-Z Dongles:
More details and instructions can be found here.
Diff: main/drv/at/ATCommandsInterface.cpp
- Revision:
- 8:04b6a042595f
- Parent:
- 7:2069ba77b6b8
- Child:
- 9:3f077dde13c9
- Child:
- 10:21a6f09d5631
--- a/main/drv/at/ATCommandsInterface.cpp Fri Jun 08 13:30:06 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,806 +0,0 @@ -/* ATCommandsInterface.cpp */ -/* -Copyright (C) 2012 ARM Limited. - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#define __DEBUG__ 2//ERR+WARN -#ifndef __MODULE__ -#define __MODULE__ "ATCommandsInterface.cpp" -#endif - -#include "core/fwk.h" - -#include <cstdio> -//#include <cstring> //For memset, strstr... - -using std::memmove; - -#include "ATCommandsInterface.h" - -ATCommandsInterface::ATCommandsInterface(IOStream* pStream) : - m_pStream(pStream), m_open(false), m_env2AT(), m_AT2Env(), m_processingMtx(), - m_processingThread(&ATCommandsInterface::staticCallback, this, (osPriority)AT_THREAD_PRIORITY, 4*192), - m_eventsMtx() -{ - memset(m_eventsHandlers, 0, MAX_AT_EVENTS_HANDLERS * sizeof(IATEventsHandler*)); - - m_processingMtx.lock(); -} - -//Open connection to AT Interface in order to execute command & register/unregister events -int ATCommandsInterface::open() -{ - if( m_open ) - { - WARN("AT interface is already open"); - return OK; - } - DBG("Opening AT interface"); - //Start processing - m_processingThread.signal_set(AT_SIG_PROCESSING_START); - - m_processingMtx.unlock(); - - m_open = true; - - //Advertize this to events handlers - m_eventsMtx.lock(); - for(int i = 0; i < MAX_AT_EVENTS_HANDLERS; i++) //Find a free slot - { - if( m_eventsHandlers[i] != NULL ) - { - m_eventsHandlers[i]->onDispatchStart(); - } - } - m_eventsMtx.unlock(); - - DBG("AT interface opened"); - - return OK; -} - -//Initialize AT link -int ATCommandsInterface::init() -{ - DBG("Sending ATZ E1 V1"); - //Should we flush m_pStream at this point ??? - int err; - int tries = 5; - do - { - err = executeSimple("ATZ E1 V1", NULL, 3000); //Enable echo and verbosity - if(err && tries) - { - WARN("No response, trying again"); - Thread::wait(1000); //Give dongle time to recover - } - } while(err && tries--); - if( err ) - { - ERR("Sending ATZ E1 V1 returned with err code %d", err); - return err; - } - - DBG("AT interface initialized"); - - return OK; -} - -//Close connection -int ATCommandsInterface::close() -{ - if( !m_open ) - { - WARN("AT interface is already closed"); - return OK; - } - - DBG("Closing AT interface"); - - //Stop processing - m_processingThread.signal_set(AT_SIG_PROCESSING_STOP); - //m_stopSphre.release(); - - int* msg = m_env2AT.alloc(osWaitForever); - *msg = AT_STOP; - m_env2AT.put(msg); //Used to unstall the process if needed - - //Unlock process routine (abort read) - m_pStream->abortRead(); //This is thread-safe - m_processingMtx.lock(); - m_open = false; - - //Advertize this to events handlers - m_eventsMtx.lock(); - for(int i = 0; i < MAX_AT_EVENTS_HANDLERS; i++) //Find a free slot - { - if( m_eventsHandlers[i] != NULL ) - { - m_eventsHandlers[i]->onDispatchStop(); - } - } - m_eventsMtx.unlock(); - - DBG("AT interface closed"); - return OK; -} - -bool ATCommandsInterface::isOpen() -{ - return m_open; -} - -int ATCommandsInterface::executeSimple(const char* command, ATResult* pResult, uint32_t timeout/*=1000*/) -{ - return execute(command, this, pResult, timeout); -} - -int ATCommandsInterface::execute(const char* command, IATCommandsProcessor* pProcessor, ATResult* pResult, uint32_t timeout/*=1000*/) -{ - DBG("Executing command %s", command); - if(!m_open) - { - WARN("Interface is not open!"); - return NET_INVALID; - } - - //Lock transaction mutex - m_transactionMtx.lock(); - - //Discard previous result if it arrived too late - osEvent evt = m_AT2Env.get(0); - - if(evt.status == osEventMail) - { - m_AT2Env.free((int*)evt.value.p); - WARN("Previous result discarded"); - } - - //Send params to the process routine - m_transactionCommand = command; - if(pProcessor != NULL) - { - m_pTransactionProcessor = pProcessor; - } - else - { - m_pTransactionProcessor = this; //Use default behaviour - } - - Thread::wait(100); //FIXME find stg else - - DBG("Sending command ready signal to AT thread & aborting current blocking read operation"); - - //Produce command ready signal - int* msg = m_env2AT.alloc(osWaitForever); - *msg = AT_CMD_READY; - m_env2AT.put(msg); - - DBG("Trying to enter abortRead()"); - //Unlock process routine (abort read) - m_pStream->abortRead(); //This is thread-safe - - //Wait for a result (get result message) - evt = m_AT2Env.get(timeout); - - if(evt.status != osEventMail) - { - //Cancel request - msg = m_env2AT.alloc(osWaitForever); - *msg = AT_TIMEOUT; - m_env2AT.put(msg); - - DBG("Trying to enter abortRead()"); - //Unlock process routine (abort read) - m_pStream->abortRead(); //This is thread-safe - - WARN("Command returned no message"); - m_transactionMtx.unlock(); - return NET_TIMEOUT; - } - DBG("Command returned with message %d", *msg); - - m_AT2Env.free((int*)evt.value.p); - - if(pResult != NULL) - { - *pResult = m_transactionResult; - } - - int ret = ATResultToReturnCode(m_transactionResult); - if(ret != OK) - { - WARN("Command returned AT result %d with code %d", m_transactionResult.result, m_transactionResult.code); - } - - DBG("Command returned successfully"); - - //Unlock transaction mutex - m_transactionMtx.unlock(); - - return ret; -} - -int ATCommandsInterface::registerEventsHandler(IATEventsHandler* pHdlr) -{ - m_eventsMtx.lock(); - for(int i = 0; i < MAX_AT_EVENTS_HANDLERS; i++) //Find a free slot - { - if( m_eventsHandlers[i] == NULL ) - { - m_eventsHandlers[i] = pHdlr; - m_eventsMtx.unlock(); - return OK; - } - } - m_eventsMtx.unlock(); - return NET_OOM; //No room left -} - -int ATCommandsInterface::deregisterEventsHandler(IATEventsHandler* pHdlr) -{ - m_eventsMtx.lock(); - for(int i = 0; i < MAX_AT_EVENTS_HANDLERS; i++) //Find handler in list - { - if( m_eventsHandlers[i] == pHdlr ) - { - m_eventsHandlers[i] = NULL; - m_eventsMtx.unlock(); - return OK; - } - } - m_eventsMtx.unlock(); - return NET_NOTFOUND; //Not found -} - - -int ATCommandsInterface::tryReadLine() -{ - static bool lineDetected = false; - - //Block on serial read or incoming command - DBG("Trying to read a new line from stream"); - int ret = m_pStream->waitAvailable(); //This can be aborted - size_t readLen = 0; - if(ret == OK) - { - ret = m_pStream->read((uint8_t*)m_inputBuf + m_inputPos, &readLen, AT_INPUT_BUF_SIZE - 1 - m_inputPos, 0); //Do NOT wait at this point - } - if(ret == OK) - { - m_inputPos+=readLen; - m_inputBuf[m_inputPos] = '\0'; //Add null terminating character to ease the use of str* functions - DBG("In buffer: [%s]", m_inputBuf); - } - - if( ret == NET_INTERRUPTED ) //It is worth checking readLen as data might have been read even though the read was interrupted - { - DBG("Read was interrupted"); - return NET_INTERRUPTED; //0 chars were read - } - else if(readLen == 0) - { - DBG("Nothing read"); - return OK; //0 chars were read - } - - DBG("Trying to process incoming line"); - bool lineProcessed = false; - - do - { - lineProcessed = false; //Reset flag - - DBG("New iteration"); - - //Look for a new line - if(!lineDetected) - { - DBG("No line detected yet"); - //Try to look for a starting CRLF - char* crPtr = strchr(m_inputBuf, CR); - /* - Different cases at this point: - - CRLF%c sequence: this is the start of a line - - CRLFCR(LF) sequence: this is the end of a line (followed by the beginning of the next one) - - LF: this is the trailing LF char of the previous line, discard - - CR / CRLF incomplete sequence: more data is needed to determine which action to take - - %c ... CR sequence: this should be the echo of the previous sequence - - %c sequence: This might be the echo of the previous command; more data is needed to determine which action to take - - In every case, move mem at the beginning - */ - if(crPtr != NULL) - { - DBG("CR char found"); - -#if 0 - //Discard all preceding characters (can do nothing if m_inputBuf == crPtr) - memmove(m_inputBuf, crPtr, (m_inputPos + 1) - (crPtr-m_inputBuf)); //Move null-terminating char as well - m_inputPos = m_inputPos - (crPtr-m_inputBuf); //Adjust m_inputPos -#endif - - //If the line starts with CR, this should be a result code - if( crPtr == m_inputBuf ) - { - //To determine the sequence we need at least 3 chars - if(m_inputPos >= 3) - { - //Look for a LF char next to the CR char - if(m_inputBuf[1] == LF) - { - //At this point we can check whether this is the end of a preceding line or the beginning of a new one - if(m_inputBuf[2] != CR) - { - DBG("Beginning of new line found"); - //Beginning of a line - lineDetected = true; //Move to next state-machine step - } - else - { - //End of an unprocessed line - WARN("End of unprocessed line"); - } - //In both cases discard CRLF - DBG("Discarding CRLF"); - memmove(m_inputBuf, m_inputBuf + 2, (m_inputPos + 1) - 2); //Move null-terminating char as well - m_inputPos = m_inputPos - 2; //Adjust m_inputPos - } - else - { - //This is completely unexpected, discard the CR char to try to recover good state - WARN("Unexpected %c char (%02d code) found after CR char", m_inputBuf[1]); - memmove(m_inputBuf, m_inputBuf + 1, (m_inputPos + 1) - 1); //Move null-terminating char as well - m_inputPos = m_inputPos - 1; //Adjust m_inputPos - } - } - } - //if the line does NOT begin with CR, this can be an echo of the previous command, process it - else - { - int crPos = crPtr - m_inputBuf; - int lfOff = 0; //Offset for LF if present - DBG("New line found (possible echo of command)"); - //This is the end of line - //Replace m_inputBuf[crPos] with null-terminating char - m_inputBuf[crPos] = '\0'; - //Check if there is a LF char afterwards - if(m_inputPos - crPos >= 1) - { - if(m_inputBuf[crPos+1] == LF) - { - lfOff++; //We will discard LF char as well - } - } - //Process line - processReadLine(); - //Shift remaining data to beginning of buffer - memmove(m_inputBuf, m_inputBuf + crPos + lfOff + 1, (m_inputPos + 1) - (crPos + lfOff + 1)); //Move null-terminating char as well - m_inputPos = m_inputPos - (crPos + lfOff + 1); //Adjust m_inputPos - DBG("One line was successfully processed"); - lineProcessed = true; //Line was processed with success - lineDetected = false; //Search now for a new line - } - } - else if(m_inputBuf[0] == LF) //If there is a remaining LF char from the previous line, discard it - { - DBG("Discarding single LF char"); - memmove(m_inputBuf, m_inputBuf + 1, (m_inputPos + 1) - 1); //Move null-terminating char as well - m_inputPos = m_inputPos - 1; //Adjust m_inputPos - } - } - - //Look for the end of line - if(lineDetected) - { - DBG("Looking for end of line"); - //Try to look for a terminating CRLF - char* crPtr = strchr(m_inputBuf, CR); - /* - Different cases at this point: - - CRLF sequence: this is the end of the line - - CR%c sequence : unexpected - - CR incomplete sequence: more data is needed to determine which action to take - */ - - //Try to look for a '>' (greater than character) that marks an entry prompt - char* greaterThanPtr = strchr(m_inputBuf, GD); - /* - This character must be detected as there is no CRLF sequence at the end of an entry prompt - */ - - if(crPtr != NULL) - { - DBG("CR char found"); - int crPos = crPtr - m_inputBuf; - //To determine the sequence we need at least 2 chars - if(m_inputPos - crPos >= 2) - { - //Look for a LF char next to the CR char - if(m_inputBuf[crPos + 1] == LF) - { - DBG("End of new line found"); - //This is the end of line - //Replace m_inputBuf[crPos] with null-terminating char - m_inputBuf[crPos] = '\0'; - //Process line - int ret = processReadLine(); - if(ret) - { - m_inputPos = 0; - lineDetected = false; - return ret; - } - - //If sendData has been called, all incoming data has been discarded - if(m_inputPos > 0) - { - //Shift remaining data to beginning of buffer - memmove(m_inputBuf, m_inputBuf + crPos + 2, (m_inputPos + 1) - (crPos + 2)); //Move null-terminating char as well - m_inputPos = m_inputPos - (crPos + 2); //Adjust m_inputPos - } - - DBG("One line was successfully processed"); - lineProcessed = true; //Line was processed with success - } - else - { - //This is completely unexpected, discard all chars till the CR char to try to recover good state - WARN("Unexpected %c char (%02d code) found in incoming line", m_inputBuf[crPos + 1]); - memmove(m_inputBuf, m_inputBuf + crPos + 1, (m_inputPos + 1) - (crPos + 1)); //Move null-terminating char as well - m_inputPos = m_inputPos - (crPos + 1); //Adjust m_inputPos - } - lineDetected = false; //In both case search now for a new line - } - } - else if(greaterThanPtr != NULL) - { - DBG("> char found"); - int gdPos = greaterThanPtr - m_inputBuf; - //To determine the sequence we need at least 2 chars - if(m_inputPos - gdPos >= 2) - { - //Look for a space char next to the GD char - if(m_inputBuf[gdPos + 1] == ' ') - { - //This is an entry prompt - //Replace m_inputBuf[gdPos] with null-terminating char - m_inputBuf[gdPos] = '\0'; - - //Shift remaining data to beginning of buffer - memmove(m_inputBuf, m_inputBuf + gdPos + 1, (m_inputPos + 1) - (gdPos + 1)); //Move null-terminating char as well - m_inputPos = m_inputPos - (gdPos + 1); //Adjust m_inputPos - - //Process prompt - ret = processEntryPrompt(); - if(ret) - { - m_inputPos = 0; - lineDetected = false; - return ret; - } - - DBG("One line was successfully processed"); - lineProcessed = true; //Line was processed with success - } - else - { - //This is completely unexpected, discard all chars till the GD char to try to recover good state - WARN("Unexpected %c char (%02d code) found in incoming line", m_inputBuf[gdPos + 1]); - memmove(m_inputBuf, m_inputBuf + gdPos + 1, (m_inputPos + 1) - (gdPos + 1)); //Move null-terminating char as well - m_inputPos = m_inputPos - (gdPos + 1); //Adjust m_inputPos - } - lineDetected = false; //In both case search now for a new line - } - } - } - } while(lineProcessed); //If one complete line was processed there might be other incoming lines that can also be processed without reading the buffer again - - //If the line could not be processed AND buffer is full, it means that we won't ever be able to process it (buffer too short) - if(m_inputPos == AT_INPUT_BUF_SIZE - 1) - { - //Discard everything - m_inputPos = 0; - WARN("Incoming buffer is too short to process incoming line"); - //Look for a new line - lineDetected = false; - } - - DBG("Processed every full incoming lines"); - - return OK; -} - -int ATCommandsInterface::trySendCommand() -{ - osEvent evt = m_env2AT.get(0); - DBG("status = %d, msg = %d", evt.status, evt.value.p); - if(evt.status == osEventMail) - { - int* msg = (int*) evt.value.p; - if( *msg == AT_CMD_READY ) //Command pending - { - if(m_transactionState != IDLE) - { - WARN("Previous command not processed!"); - } - DBG("Sending pending command"); - m_pStream->write((uint8_t*)m_transactionCommand, strlen(m_transactionCommand), osWaitForever); - char cr = CR; - m_pStream->write((uint8_t*)&cr, 1, osWaitForever); //Carriage return line terminator - m_transactionState = COMMAND_SENT; - } - else - { - m_transactionState = IDLE; //State-machine reset - } - m_env2AT.free(msg); - } - return OK; -} - -int ATCommandsInterface::processReadLine() -{ - DBG("Processing read line [%s]", m_inputBuf); - //The line is stored in m_inputBuf - if(m_transactionState == COMMAND_SENT) - { - //If the command has been sent, checks echo to see if it has been received properly - if( strcmp(m_transactionCommand, m_inputBuf) == 0 ) - { - DBG("Command echo received"); - //If so, it means that the following lines will only be solicited results - m_transactionState = READING_RESULT; - return OK; - } - } - if(m_transactionState == IDLE || m_transactionState == COMMAND_SENT) - { - bool found = false; - char* pSemicol = strchr(m_inputBuf, ':'); - char* pData = NULL; - if( pSemicol != NULL ) //Split the identifier & the result code (if it exists) - { - *pSemicol = '\0'; - pData = pSemicol + 1; - if(pData[0]==' ') - { - pData++; //Suppress whitespace - } - } - //Looks for a unsolicited result code; we can have m_transactionState == COMMAND_SENT as the code may have arrived just before we sent the command - m_eventsMtx.lock(); - //Go through the list - for(int i = 0; i < MAX_AT_EVENTS_HANDLERS; i++) //Find a free slot - { - if( m_eventsHandlers[i] != NULL ) - { - if( m_eventsHandlers[i]->isATCodeHandled(m_inputBuf) ) - { - m_eventsHandlers[i]->onEvent(m_inputBuf, pData); - found = true; //Do not break here as there might be multiple handlers for one event type - } - } - } - m_eventsMtx.unlock(); - if(found) - { - return OK; - } - } - if(m_transactionState == READING_RESULT) - { - //The following lines can either be a command response or a result code (OK / ERROR / CONNECT / +CME ERROR: %s / +CMS ERROR: %s) - if(strcmp("OK", m_inputBuf) == 0) - { - DBG("OK result received"); - m_transactionResult.code = 0; - m_transactionResult.result = ATResult::AT_OK; - m_transactionState = IDLE; - int* msg = m_AT2Env.alloc(osWaitForever); - *msg = AT_RESULT_READY; - m_AT2Env.put(msg); //Command has been processed - return OK; - } - else if(strcmp("ERROR", m_inputBuf) == 0) - { - DBG("ERROR result received"); - m_transactionResult.code = 0; - m_transactionResult.result = ATResult::AT_ERROR; - m_transactionState = IDLE; - int* msg = m_AT2Env.alloc(osWaitForever); - *msg = AT_RESULT_READY; - m_AT2Env.put(msg); //Command has been processed - return OK; - } - else if(strncmp("CONNECT", m_inputBuf, 7 /*=strlen("CONNECT")*/) == 0) //Result can be "CONNECT" or "CONNECT %d", indicating baudrate - { - DBG("CONNECT result received"); - m_transactionResult.code = 0; - m_transactionResult.result = ATResult::AT_CONNECT; - m_transactionState = IDLE; - int* msg = m_AT2Env.alloc(osWaitForever); - *msg = AT_RESULT_READY; - m_AT2Env.put(msg); //Command has been processed - return OK; - } - else if(strcmp("COMMAND NOT SUPPORT", m_inputBuf) == 0) //Huawei-specific, not normalized - { - DBG("COMMAND NOT SUPPORT result received"); - m_transactionResult.code = 0; - m_transactionResult.result = ATResult::AT_ERROR; - m_transactionState = IDLE; - int* msg = m_AT2Env.alloc(osWaitForever); - *msg = AT_RESULT_READY; - m_AT2Env.put(msg); //Command has been processed - return OK; - } - else if(strstr(m_inputBuf, "+CME ERROR:") == m_inputBuf) //Mobile Equipment Error - { - std::sscanf(m_inputBuf + 12 /* =strlen("+CME ERROR: ") */, "%d", &m_transactionResult.code); - DBG("+CME ERROR: %d result received", m_transactionResult.code); - m_transactionResult.result = ATResult::AT_CME_ERROR; - m_transactionState = IDLE; - int* msg = m_AT2Env.alloc(osWaitForever); - *msg = AT_RESULT_READY; - m_AT2Env.put(msg); //Command has been processed - return OK; - } - else if(strstr(m_inputBuf, "+CMS ERROR:") == m_inputBuf) //SIM Error - { - std::sscanf(m_inputBuf + 13 /* =strlen("+CME ERROR: ") */, "%d", &m_transactionResult.code); - DBG("+CMS ERROR: %d result received", m_transactionResult.code); - m_transactionResult.result = ATResult::AT_CMS_ERROR; - m_transactionState = IDLE; - int* msg = m_AT2Env.alloc(osWaitForever); - *msg = AT_RESULT_READY; - m_AT2Env.put(msg); //Command has been processed - return OK; - } - else - { - DBG("Unprocessed result received: '%s'", m_inputBuf); - //Must call transaction processor to complete line processing - int ret = m_pTransactionProcessor->onNewATResponseLine(this, m_inputBuf); //Here sendData can be called - return ret; - } - } - - return OK; -} - -int ATCommandsInterface::processEntryPrompt() -{ - DBG("Calling prompt handler"); - int ret = m_pTransactionProcessor->onNewEntryPrompt(this); //Here sendData can be called - - if( ret != NET_MOREINFO ) //A new prompt is expected - { - DBG("Sending break character"); - //Send CTRL+Z (break sequence) to exit prompt - char seq[2] = {BRK, 0x00}; - sendData(seq); - } - return OK; -} - -//Commands that can be called during onNewATResponseLine callback, additionally to close() -//Access to this method is protected (can ONLY be called on processing thread during IATCommandsProcessor::onNewATResponseLine execution) -int ATCommandsInterface::sendData(const char* data) -{ - //m_inputBuf is cleared at this point (and MUST therefore be empty) - int dataLen = strlen(data); - DBG("Sending raw string of length %d", dataLen); - int ret = m_pStream->write((uint8_t*)data, dataLen, osWaitForever); - if(ret) - { - WARN("Could not write to stream (returned %d)", ret); - return ret; - } - - int dataPos = 0; - do - { - //Read echo - size_t readLen; - int ret = m_pStream->read((uint8_t*)m_inputBuf, &readLen, MIN(dataLen - dataPos, AT_INPUT_BUF_SIZE - 1), osWaitForever); //Make sure we do not read more than needed otherwise it could break the parser - if(ret) - { - WARN("Could not read from stream (returned %d)", ret); - return ret; - }; - - if( memcmp(m_inputBuf, data + dataPos, readLen) != 0 ) - { - //Echo does not match output - WARN("Echo does not match output"); - return NET_DIFF; - } - - dataPos += readLen; - //If all characters have not been read yet - - } while(dataPos < dataLen); - - DBG("String sent successfully"); - - m_inputPos = 0; //Reset input buffer state - - return OK; -} - -/*static*/ void ATCommandsInterface::staticCallback(void const* p) -{ - ((ATCommandsInterface*)p)->process(); -} - -int ATCommandsInterface::ATResultToReturnCode(ATResult result) //Helper -{ - if(result.result == ATResult::AT_OK) - { - return OK; - } - else - { - return NET_MOREINFO; - } -} - -/*virtual*/ int ATCommandsInterface::onNewATResponseLine(ATCommandsInterface* pInst, const char* line) //Default implementation for simple commands handling -{ - return OK; -} - -/*virtual*/ int ATCommandsInterface::onNewEntryPrompt(ATCommandsInterface* pInst) //Default implementation (just sends Ctrl+Z to exit the prompt by returning OK right-away) -{ - return OK; -} - -void ATCommandsInterface::process() //Processing thread -{ - DBG("AT Thread started"); - while(true) - { - DBG("AT Processing on hold"); - m_processingThread.signal_wait(AT_SIG_PROCESSING_START); //Block until the process is started - - m_processingMtx.lock(); - DBG("AT Processing started"); - //First of all discard buffer - int ret; - size_t readLen; - do //Drop everything - { - ret = m_pStream->read((uint8_t*)m_inputBuf, &readLen, AT_INPUT_BUF_SIZE - 1, 0); //Do NOT wait at this point - } while(ret == OK); - m_inputPos = 0; //Clear input buffer - do - { - DBG("Trying to read a new line"); - tryReadLine(); - DBG("Trying to send a pending command"); - trySendCommand(); - } while( m_processingThread.signal_wait(AT_SIG_PROCESSING_STOP, 0).status != osEventSignal ); //Loop until the process is interrupted - m_processingMtx.unlock(); - DBG("AT Processing stopped"); - } -} -