local fork

Dependencies:   Socket USBHostWANDongle_bleedingedge lwip-sys lwip

Dependents:   Encrypted

Fork of VodafoneUSBModem_bleedingedge by Donatien Garnier

Revision:
57:593fb493172f
Parent:
55:07b9b48cfe09
Child:
58:763eefc845b1
--- a/at/ATCommandsInterface.cpp	Mon Oct 22 15:47:01 2012 +0000
+++ b/at/ATCommandsInterface.cpp	Wed Oct 24 14:13:49 2012 +0000
@@ -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,44 +271,10 @@
 
   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
-}
-
+#include "mbed.h"
+DigitalOut led_test(LED4);
 
 int ATCommandsInterface::tryReadLine()
 {
@@ -274,12 +282,14 @@
 
   //Block on serial read or incoming command
   DBG("Trying to read a new line from stream");
+  led_test=1;
   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
   }
+  led_test=0;
   if(ret == OK)
   {
     m_inputPos+=readLen;
@@ -597,7 +607,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 +620,7 @@
         }
       }
     }
-    m_eventsMtx.unlock();
+    m_eventsProcessingMtx.unlock();
     if(found)
     {
       return OK;
@@ -712,6 +722,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 +801,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 +868,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");