Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: Socket USBHostWANDongleSprint lwip-sys lwip
Dependents: SprintUSBModemWebsocketTest SprintUSBModemHTTPClientTest SprintUSBModemNTPClientTest SprintUSBModemSMSTest ... more
Fork of SprintUSBModem_bleedingedge by
Diff: at/ATCommandsInterface.cpp
- Revision:
- 10:35496211da8f
- Parent:
- 4:23100b0757d6
--- 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");
