USB Host Library for Sprint Dongles
Dependencies: Socket USBHostWANDongleSprint lwip-sys lwip
Dependents: SprintUSBModemWebsocketTest SprintUSBModemHTTPClientTest SprintUSBModemNTPClientTest SprintUSBModemSMSTest ... more
Fork of SprintUSBModem_bleedingedge by
Revision 10:35496211da8f, committed 2012-10-30
- Comitter:
- donatien
- Date:
- Tue Oct 30 12:40:18 2012 +0000
- Parent:
- 7:098c2adcc17a
- Child:
- 11:7e1056a4ca50
- Commit message:
- Extensive support for unsolicited result codes
Changed in this revision
at/ATCommandsInterface.cpp | Show annotated file Show diff for this revision Revisions of this file |
at/ATCommandsInterface.h | Show annotated file Show diff for this revision Revisions of this file |
--- a/at/ATCommandsInterface.cpp Wed Oct 24 15:14:24 2012 +0000 +++ b/at/ATCommandsInterface.cpp Tue Oct 30 12:40:18 2012 +0000 @@ -17,7 +17,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#define __DEBUG__ 2//ERR+WARN +#define __DEBUG__ 2 //ERR+WARN #ifndef __MODULE__ #define __MODULE__ "ATCommandsInterface.cpp" #endif @@ -34,7 +34,7 @@ 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() + m_eventsMgmtMtx(), m_eventsProcessingMtx() { memset(m_eventsHandlers, 0, MAX_AT_EVENTS_HANDLERS * sizeof(IATEventsHandler*)); @@ -57,32 +57,25 @@ 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 +//Initialize AT link & start events processing int ATCommandsInterface::init() { DBG("Sending ATZ E1 V1"); + + //Lock transaction mutex + m_transactionMtx.lock(); + //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 + err = executeInternal("ATZ E1 V1", this, NULL, 3000); //Enable echo and verbosity if(err && tries) { WARN("No response, trying again"); @@ -92,10 +85,17 @@ if( err ) { ERR("Sending ATZ E1 V1 returned with err code %d", err); + m_transactionMtx.unlock(); return err; } + + //Enable events handling and execute events enabling commands + enableEvents(); DBG("AT interface initialized"); + + //Unlock transaction mutex + m_transactionMtx.unlock(); return OK; } @@ -124,16 +124,8 @@ 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(); + //Disable events handling and advertize this to the events handlers + disableEvents(); DBG("AT interface closed"); return OK; @@ -151,7 +143,6 @@ 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!"); @@ -160,6 +151,60 @@ //Lock transaction mutex m_transactionMtx.lock(); + + disableEvents(); //Disable unsollicited result codes + int ret = executeInternal(command, pProcessor, pResult, timeout); + enableEvents(); //Re-enable unsollicited result codes whatever the result of the command is + + //Unlock transaction mutex + m_transactionMtx.unlock(); + + return ret; +} + +int ATCommandsInterface::registerEventsHandler(IATEventsHandler* pHdlr) +{ + m_eventsMgmtMtx.lock(); + m_eventsProcessingMtx.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_eventsProcessingMtx.unlock(); + m_eventsMgmtMtx.unlock(); + return OK; + } + } + m_eventsProcessingMtx.unlock(); + m_eventsMgmtMtx.unlock(); + return NET_OOM; //No room left +} + +int ATCommandsInterface::deregisterEventsHandler(IATEventsHandler* pHdlr) +{ + m_eventsMgmtMtx.lock(); + m_eventsProcessingMtx.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_eventsProcessingMtx.unlock(); + m_eventsMgmtMtx.unlock(); + return OK; + } + } + m_eventsProcessingMtx.unlock(); + m_eventsMgmtMtx.unlock(); + return NET_NOTFOUND; //Not found +} + +//Private methods + +int ATCommandsInterface::executeInternal(const char* command, IATCommandsProcessor* pProcessor, ATResult* pResult, uint32_t timeout/*=1000*/) +{ + DBG("Executing command %s", command); //Discard previous result if it arrived too late osEvent evt = m_AT2Env.get(0); @@ -181,8 +226,6 @@ 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 @@ -209,7 +252,6 @@ 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); @@ -229,45 +271,9 @@ 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; @@ -597,7 +603,7 @@ } } //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(); + m_eventsProcessingMtx.lock(); //Go through the list for(int i = 0; i < MAX_AT_EVENTS_HANDLERS; i++) //Find a free slot { @@ -610,7 +616,7 @@ } } } - m_eventsMtx.unlock(); + m_eventsProcessingMtx.unlock(); if(found) { return OK; @@ -712,6 +718,54 @@ return OK; } +//This will be called on initialization & after the execution of a command +void ATCommandsInterface::enableEvents() +{ + //Advertize this to events handlers + m_eventsMgmtMtx.lock(); + for(int i = 0; i < MAX_AT_EVENTS_HANDLERS; i++) //Find a free slot + { + if( m_eventsHandlers[i] != NULL ) + { + m_eventsHandlers[i]->onDispatchStart(); + //Enable this kind of events + if(m_eventsHandlers[i]->getEventsEnableCommand() != NULL) + { + int ret = executeInternal(m_eventsHandlers[i]->getEventsEnableCommand(), this, NULL); //Execute enable command + if(ret) + { + WARN("Events enabling command failed"); + } + } + } + } + m_eventsMgmtMtx.unlock(); +} + +//This will be called on de-initialization & before the execution of a command to prevent unsollicited result codes from polluting the results +void ATCommandsInterface::disableEvents() +{ + //Advertize this to events handlers + m_eventsMgmtMtx.lock(); + for(int i = 0; i < MAX_AT_EVENTS_HANDLERS; i++) //Find a free slot + { + if( m_eventsHandlers[i] != NULL ) + { + m_eventsHandlers[i]->onDispatchStart(); + //Disable this kind of events + if(m_eventsHandlers[i]->getEventsDisableCommand() != NULL) + { + int ret = executeInternal(m_eventsHandlers[i]->getEventsDisableCommand(), this, NULL); //Execute disable command + if(ret) + { + WARN("Events disabling command failed"); + } + } + } + } + m_eventsMgmtMtx.unlock(); +} + //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) @@ -743,7 +797,8 @@ if( memcmp(m_inputBuf, data + dataPos, readLen) != 0 ) { //Echo does not match output - WARN("Echo does not match output"); + m_inputBuf[readLen] = '\0'; + WARN("Echo does not match output, got '%s' instead", m_inputBuf); m_inputPos = 0; //Reset input buffer state m_inputBuf[0] = '\0'; //Always have a null-terminating char at start of buffer return NET_DIFF; @@ -809,10 +864,10 @@ m_inputPos = 0; //Clear input buffer do { + DBG("Trying to send a pending command"); + trySendCommand(); //This must be tried first as we discarded the buffer before and therefore would be blocking though there is a pending command 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");
--- a/at/ATCommandsInterface.h Wed Oct 24 15:14:24 2012 +0000 +++ b/at/ATCommandsInterface.h Tue Oct 30 12:40:18 2012 +0000 @@ -36,6 +36,8 @@ virtual bool isATCodeHandled(const char* atCode) = 0; //Is this AT code handled virtual void onDispatchStart() = 0; virtual void onDispatchStop() = 0; + virtual char* getEventsEnableCommand() = 0; + virtual char* getEventsDisableCommand() = 0; virtual void onEvent(const char* atCode, const char* evt) = 0; friend class ATCommandsInterface; }; @@ -91,6 +93,7 @@ int executeSimple(const char* command, ATResult* pResult, uint32_t timeout=1000); int execute(const char* command, IATCommandsProcessor* pProcessor, ATResult* pResult, uint32_t timeout=1000); + int registerEventsHandler(IATEventsHandler* pHdlr); int deregisterEventsHandler(IATEventsHandler* pHdlr); @@ -100,10 +103,15 @@ static void staticCallback(void const* p); private: + int executeInternal(const char* command, IATCommandsProcessor* pProcessor, ATResult* pResult, uint32_t timeout=1000); + int tryReadLine(); int trySendCommand(); int processReadLine(); int processEntryPrompt(); + + void enableEvents(); + void disableEvents(); int ATResultToReturnCode(ATResult result); //Helper @@ -124,20 +132,22 @@ enum { IDLE, COMMAND_SENT, READING_RESULT, ABORTED } m_transactionState; - char m_inputBuf[AT_INPUT_BUF_SIZE]; - int m_inputPos; + char m_inputBuf[AT_INPUT_BUF_SIZE]; // Stores characters received from the modem. + int m_inputPos; // Current position of fill pointer in the input buffer. Mutex m_transactionMtx; - Mail<int,1> m_env2AT; - Mail<int,1> m_AT2Env; + // These are RTOS queues, concurrent access protected. In this case both only contain an integer. + Mail<int,1> m_env2AT; // used by calling function to inform processing thread of events + Mail<int,1> m_AT2Env; // used by processing thread to inform calling function of events - IATEventsHandler* m_eventsHandlers[MAX_AT_EVENTS_HANDLERS]; + IATEventsHandler* m_eventsHandlers[MAX_AT_EVENTS_HANDLERS]; // all registered events handlers Mutex m_processingMtx; Thread m_processingThread; - Mutex m_eventsMtx; + Mutex m_eventsMgmtMtx; //Lock events use within the calling thread + Mutex m_eventsProcessingMtx; //Lock events use within the processing thread }; #endif /* ATCOMMANDSINTERFACE_H_ */