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 Donatien Garnier

This is the driver for the Vodafone K3700 & K3772-Z Dongles:

K3770

More details and instructions can be found here.

Files at this revision

API Documentation at this revision

Comitter:
donatien
Date:
Tue Jun 26 13:44:59 2012 +0000
Parent:
7:2069ba77b6b8
Child:
9:3f077dde13c9
Child:
10:21a6f09d5631
Commit message:
Bleeding edge - test with two different interfaces

Changed in this revision

LwIPNetworking.lib Show annotated file Show diff for this revision Revisions of this file
USBHostWANDongleLib.lib Show annotated file Show diff for this revision Revisions of this file
VodafoneK3770.cpp Show annotated file Show diff for this revision Revisions of this file
VodafoneK3770.h Show annotated file Show diff for this revision Revisions of this file
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
contrib/vodafone/if/VodafoneK3770.cpp Show diff for this revision Revisions of this file
contrib/vodafone/if/VodafoneK3770.h Show diff for this revision Revisions of this file
contrib/vodafone/if/vodafone/VodafoneManager.h Show diff for this revision Revisions of this file
ip/PPPIPInterface.cpp Show annotated file Show diff for this revision Revisions of this file
ip/PPPIPInterface.h Show annotated file Show diff for this revision Revisions of this file
lwipopts.h Show annotated file Show diff for this revision Revisions of this file
main/drv/at/ATCommandsInterface.cpp Show diff for this revision Revisions of this file
main/drv/at/ATCommandsInterface.h Show diff for this revision Revisions of this file
main/drv/serial/io/IOSerialStream.cpp Show diff for this revision Revisions of this file
main/drv/serial/io/IOSerialStream.h Show diff for this revision Revisions of this file
main/drv/serial/usb/USBSerialStream.cpp Show diff for this revision Revisions of this file
main/drv/serial/usb/USBSerialStream.h Show diff for this revision Revisions of this file
main/if/ip/PPPIPInterface.cpp Show diff for this revision Revisions of this file
main/if/ip/PPPIPInterface.h Show diff for this revision Revisions of this file
main/if/sms/SMSInterface.cpp Show diff for this revision Revisions of this file
main/if/sms/SMSInterface.h Show diff for this revision Revisions of this file
main/if/ussd/USSDInterface.cpp Show diff for this revision Revisions of this file
main/if/ussd/USSDInterface.h Show diff for this revision Revisions of this file
main/lwipopts.h Show diff for this revision Revisions of this file
serial/io/IOSerialStream.cpp Show annotated file Show diff for this revision Revisions of this file
serial/io/IOSerialStream.h Show annotated file Show diff for this revision Revisions of this file
serial/usb/USBSerialStream.cpp Show annotated file Show diff for this revision Revisions of this file
serial/usb/USBSerialStream.h Show annotated file Show diff for this revision Revisions of this file
sms/SMSInterface.cpp Show annotated file Show diff for this revision Revisions of this file
sms/SMSInterface.h Show annotated file Show diff for this revision Revisions of this file
ussd/USSDInterface.cpp Show annotated file Show diff for this revision Revisions of this file
ussd/USSDInterface.h Show annotated file Show diff for this revision Revisions of this file
--- a/LwIPNetworking.lib	Fri Jun 08 13:30:06 2012 +0000
+++ b/LwIPNetworking.lib	Tue Jun 26 13:44:59 2012 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/donatien/code/LwIPNetworking/#567bdc7f0dd8
+http://mbed.org/users/donatien/code/LwIPNetworking/#cf5f669a30bc
--- a/USBHostWANDongleLib.lib	Fri Jun 08 13:30:06 2012 +0000
+++ b/USBHostWANDongleLib.lib	Tue Jun 26 13:44:59 2012 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/donatien/code/USBHostWANDongleLib/#49df46e3295c
+http://mbed.org/users/donatien/code/USBHostWANDongle_bleedingedge/#a8b2d0cd9bbd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VodafoneK3770.cpp	Tue Jun 26 13:44:59 2012 +0000
@@ -0,0 +1,474 @@
+/* VodafoneK3770.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__ 4
+#ifndef __MODULE__
+#define __MODULE__ "VodafoneK3770.cpp"
+#endif
+
+#include "core/fwk.h"
+
+#include "VodafoneK3770.h"
+
+VodafoneK3770::VodafoneK3770() : m_dongle(),
+m_atStream(m_dongle.getSerial(1)), m_pppStream(m_dongle.getSerial(0)), m_at(&m_atSream),
+m_ppp(&m_pppStream), m_sms(&m_at), m_ussd(&m_at),
+m_dongleConnected(false), m_ipInit(false), m_smsInit(false), m_atOpen(false)
+{
+
+}
+
+class CREGProcessor : public IATCommandsProcessor
+{
+public:
+  CREGProcessor() : status(STATUS_REGISTERING)
+  {
+
+  }
+  enum REGISTERING_STATUS { STATUS_REGISTERING, STATUS_OK, STATUS_FAILED };
+  REGISTERING_STATUS getStatus()
+  {
+    return status;
+  }
+private:
+  virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
+  {
+    int r;
+    if( sscanf(line, "+CREG: %*d,%d", &r) == 1 )
+    {
+      switch(r)
+      {
+      case 1:
+      case 5:
+        status = STATUS_OK;
+        break;
+      case 0:
+      case 2:
+        status = STATUS_REGISTERING;
+        break;
+      case 3:
+      default:
+        status = STATUS_FAILED;
+        break;
+      }
+    }
+    return OK;
+  }
+  virtual int onNewEntryPrompt(ATCommandsInterface* pInst)
+  {
+    return OK;
+  }
+  volatile REGISTERING_STATUS status;
+};
+
+class COPSProcessor : public IATCommandsProcessor
+{
+public:
+  COPSProcessor() : valid(false)
+  {
+    network[0] = '\0';
+    apn[0] = '\0';
+    bearer[0] = '\0';
+  }
+  char* getNetwork()
+  {
+    return network;
+  }
+  char* getAPN()
+  {
+    return apn;
+  }
+  char* getBearer()
+  {
+    return bearer;
+  }
+  bool isValid()
+  {
+    return valid;
+  }
+private:
+  virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
+  {
+    int networkId;
+    int bearerId;
+    int s = sscanf(line, "+COPS: %*d,%*d,\"%d\",%d", &networkId, &bearerId);
+    if( s == 2 )
+    {
+      switch(networkId)
+      {
+      case 23415:
+        strcpy(network, "Vodafone UK");
+        strcpy(apn, "pp.vodafone.co.uk");
+        valid = true;
+        break;
+      case 20810:
+        strcpy(network, "SFR FR");
+        strcpy(apn, "websfr");
+        valid = true;
+        break;
+      default:
+        break;
+      }
+    }
+    else
+    {
+      return OK;
+    }
+    switch(bearerId)
+    {
+    case 0: strcpy(bearer, "GSM"); break;
+    case 1: strcpy(bearer, "GSM Compact"); break;
+    case 2: strcpy(bearer, "UTRAN"); break;
+    case 3: strcpy(bearer, "GSM w/EGPRS"); break;
+    case 4: strcpy(bearer, "UTRAN w/HSDPA"); break;
+    case 5: strcpy(bearer, "UTRAN w/HSUPA"); break;
+    case 6: strcpy(bearer, "UTRAN w/HSDPA and HSUPA"); break;
+    case 7: strcpy(bearer, "E-UTRAN"); break;
+
+    default:
+      break;
+    }
+    return OK;
+  }
+  virtual int onNewEntryPrompt(ATCommandsInterface* pInst)
+  {
+    return OK;
+  }
+  char network[24];
+  char bearer[24];
+  char apn[24];
+  volatile bool valid;
+};
+
+
+int VodafoneK3770::connect(const char* apn, const char* user, const char* password)
+{
+  if( !m_ipInit )
+  {
+    m_ipInit = true;
+    m_ppp.init();
+  }
+  m_ppp.setup(user, password);
+
+  int ret = init();
+  if(ret)
+  {
+    return ret;
+  }
+
+  m_smsInit = false; //SMS status reset
+  m_ussdInit = false; //USSD status reset
+
+  ATCommandsInterface::ATResult result;
+
+#if 0
+  //Get network info & select corresponding APN
+  COPSProcessor copsProcessor;
+  DBG("Get network info & select APN from DB");
+  ret = m_at.execute("AT+COPS=,2;+COPS?", &copsProcessor, &result); //Configure to get operator's info in numeric code & get operator's id
+  DBG("Result of command: Err code=%d", ret);
+  DBG("ATResult: AT return=%d (code %d)", result.result, result.code);
+
+  if(!copsProcessor.isValid())
+  {
+    WARN("Connected to an unknown network, try to connect with default parameters");
+    DBG("Connected with %s", copsProcessor.getBearer());
+  }
+  else
+  {
+    DBG("Connected to %s with %s", copsProcessor.getNetwork(), copsProcessor.getBearer());
+    char cmd[48];
+    sprintf(cmd, "AT+CGDCONT=1,\"IP\",\"%s\"", copsProcessor.getAPN());
+    ret = m_at.executeSimple(cmd, &result);
+    DBG("Result of command: Err code=%d", ret);
+    DBG("ATResult: AT return=%d (code %d)", result.result, result.code);
+    DBG("APN set to %s", copsProcessor.getAPN());
+  }
+  #else
+  if(apn != NULL)
+  {
+    char cmd[48];
+    sprintf(cmd, "AT+CGDCONT=1,\"IP\",\"%s\"", apn);
+    ret = m_at.executeSimple(cmd, &result);
+    DBG("Result of command: Err code=%d", ret);
+    DBG("ATResult: AT return=%d (code %d)", result.result, result.code);
+    DBG("APN set to %s", apn);
+  }
+  #endif
+
+
+  //Connect
+  DBG("Connecting");
+  ret = m_at.executeSimple("ATDT *99#", &result);
+  DBG("Result of command: Err code=%d", ret);
+  DBG("ATResult: AT return=%d (code %d)", result.result, result.code);
+  m_at.close(); // Closing AT parser
+  m_atOpen = false; //Will need to be reinitialized afterwards
+
+  DBG("AT Parser closed");
+  if( (ret!=NET_MOREINFO) || (result.result != ATCommandsInterface::ATResult::AT_CONNECT))
+  {
+    ERR("Could not connect");
+    return ret; //Could not connect
+  }
+  DBG("Connecting PPP");
+
+  ret = m_ppp.connect();
+  DBG("Result of connect: Err code=%d", ret);
+  return ret;
+}
+
+
+int VodafoneK3770::disconnect()
+{
+  DBG("Disconnecting from PPP");
+  int ret = m_ppp.disconnect();
+  if(ret)
+  {
+    ERR("Disconnect returned %d, still trying to disconnect", ret);
+  }
+
+  //Ugly but leave dongle time to recover
+  Thread::wait(500);
+
+  ATCommandsInterface::ATResult result;
+  DBG("Starting AT thread");
+  ret = m_at.open();
+  if(ret)
+  {
+    return ret;
+  }
+
+  DBG("Trying to hangup");
+
+#if 0 //Does not appear to work
+  int tries = 10;
+  do
+  {
+    ret = m_at.executeSimple("+++", &result, 1000);
+    DBG("Result of command: Err code=%d\n", ret);
+    DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code);
+  } while(tries-- && ret);
+  if(!ret)
+  {
+    ret = m_at.executeSimple("ATH", &result);
+    DBG("Result of command: Err code=%d\n", ret);
+    DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code);
+  }
+#endif
+
+  //Reinit AT parser
+  ret = m_at.init();
+  DBG("Result of command: Err code=%d\n", ret);
+  if(ret)
+  {
+    m_at.close(); // Closing AT parser
+    DBG("AT Parser closed, could not complete disconnection");
+    return NET_TIMEOUT;
+  }
+
+  m_at.close(); // Closing AT parser
+  DBG("AT Parser closed");
+  return OK;
+}
+
+int VodafoneK3770::sendSM(const char* number, const char* message)
+{
+  int ret = init();
+  if(ret)
+  {
+    return ret;
+  }
+
+  if(!m_smsInit)
+  {
+    ret = m_sms.init();
+    if(ret)
+    {
+      return ret;
+    }
+    m_smsInit = true;
+  }
+
+  ret = m_sms.send(number, message);
+  if(ret)
+  {
+    return ret;
+  }
+
+  return OK;
+}
+
+int VodafoneK3770::getSM(char* number, char* message, size_t maxLength)
+{
+  int ret = init();
+  if(ret)
+  {
+    return ret;
+  }
+
+  if(!m_smsInit)
+  {
+    ret = m_sms.init();
+    if(ret)
+    {
+      return ret;
+    }
+    m_smsInit = true;
+  }
+
+  ret = m_sms.get(number, message, maxLength);
+  if(ret)
+  {
+    return ret;
+  }
+
+  return OK;
+}
+
+int VodafoneK3770::getSMCount(size_t* pCount)
+{
+  int ret = init();
+  if(ret)
+  {
+    return ret;
+  }
+
+  if(!m_smsInit)
+  {
+    ret = m_sms.init();
+    if(ret)
+    {
+      return ret;
+    }
+    m_smsInit = true;
+  }
+
+  ret = m_sms.getCount(pCount);
+  if(ret)
+  {
+    return ret;
+  }
+
+  return OK;
+}
+
+int VodafoneK3770::sendUSSD(const char* command, char* result, size_t maxLength)
+{
+  int ret = init();
+  if(ret)
+  {
+    return ret;
+  }
+
+  if(!m_ussdInit)
+  {
+    ret = m_ussd.init();
+    if(ret)
+    {
+      return ret;
+    }
+    m_ussdInit = true;
+  }
+
+  ret = m_ussd.send(command, result, maxLength);
+  if(ret)
+  {
+    return ret;
+  }
+
+  return OK;
+}
+
+ATCommandsInterface* VodafoneK3770::getATCommandsInterface()
+{
+  return &m_at;
+}
+
+int VodafoneK3770::init()
+{
+  if( !m_dongleConnected )
+  {
+    m_dongleConnected = true;
+    while( !m_dongle.connected() )
+    {
+      m_dongle.tryConnect();
+      Thread::wait(10);
+    }
+  }
+
+  if(m_atOpen)
+  {
+    return OK;
+  }
+
+  DBG("Starting AT thread if needed");
+  int ret = m_at.open();
+  if(ret)
+  {
+    return ret;
+  }
+
+  DBG("Sending initialisation commands");
+  ret = m_at.init();
+  if(ret)
+  {
+    return ret;
+  }
+
+  DBG("Configuring unsolicited result codes support properly");
+  //Configuring port
+  ret = m_at.executeSimple("AT^CURC=0;^PORTSEL=1", NULL); //Huawei-specific, not 3GPP-compliant
+  if(ret != OK)
+  {
+    return NET_PROTOCOL;
+  }
+
+  ATCommandsInterface::ATResult result;
+
+  //Wait for network registration
+  CREGProcessor cregProcessor;
+  do
+  {
+    DBG("Waiting for network registration");
+    ret = m_at.execute("AT+CREG?", &cregProcessor, &result);
+    DBG("Result of command: Err code=%d\n", ret);
+    DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code);
+    if(cregProcessor.getStatus() == CREGProcessor::STATUS_REGISTERING)
+    {
+      Thread::wait(3000);
+    }
+  } while(cregProcessor.getStatus() == CREGProcessor::STATUS_REGISTERING);
+  if(cregProcessor.getStatus() == CREGProcessor::STATUS_FAILED)
+  {
+    ERR("Registration denied");
+    return NET_AUTH;
+  }
+
+  m_atOpen = true;
+
+  return OK;
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VodafoneK3770.h	Tue Jun 26 13:44:59 2012 +0000
@@ -0,0 +1,118 @@
+/* VodafoneK3770.h */
+/*
+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.
+*/
+
+#ifndef VODAFONEK3770_H_
+#define VODAFONEK3770_H_
+
+#include "core/fwk.h"
+
+#include "WANDongle.h"
+#include "at/ATCommandsInterface.h"
+#include "serial/usb/USBSerialStream.h"
+#include "ip/PPPIPInterface.h"
+#include "sms/SMSInterface.h"
+#include "ussd/USSDInterface.h"
+
+/** Vodafone K3770 dongle
+ */
+class VodafoneK3770
+{
+public:
+  /** Create Vodafone K3770 dongle API instance
+
+   */
+  VodafoneK3770();
+
+  //Internet-related functions
+
+  /** Open a 3G internet connection
+      @return 0 on success, error code on failure
+  */
+  int connect(const char* apn = NULL, const char* user = NULL, const char* password = NULL);
+
+  /** Close the internet connection
+     @return 0 on success, error code on failure
+  */
+  int disconnect();
+
+
+  /** Send a SM
+     @param number The receiver's phone number
+     @param message The message to send
+     @return 0 on success, error code on failure
+   */
+  int sendSM(const char* number, const char* message);
+
+
+  /** Receive a SM
+     @param number Pointer to a buffer to store the sender's phone number (must be at least 17 characters-long, including the sapce for the null-terminating char)
+     @param message Pointer to a buffer to store the the incoming message
+     @param maxLength Maximum message length that can be stored in buffer (including null-terminating character)
+     @return 0 on success, error code on failure
+   */
+  int getSM(char* number, char* message, size_t maxLength);
+
+  /** Get the number of SMs in the incoming box
+     @param pCount pointer to store the number of unprocessed SMs on
+     @return 0 on success, error code on failure
+   */
+  int getSMCount(size_t* pCount);
+
+  /** Send a USSD command & wait for its result
+    @param command The command to send
+    @param result Buffer in which to store the result
+    @param maxLength Maximum result length that can be stored in buffer (including null-terminating character)
+    @return 0 on success, error code on failure
+  */
+  int sendUSSD(const char* command, char* result, size_t maxLength);
+
+  /** Get the ATCommandsInterface instance
+     @return Pointer to the ATCommandsInterface instance
+   */
+  ATCommandsInterface* getATCommandsInterface();
+
+protected:
+  int init();
+
+private:
+  WANDongle m_dongle;
+  
+  USBSerialStream m_atStream;
+  USBSerialStream m_pppStream;
+  
+  ATCommandsInterface m_at;
+  
+  SMSInterface m_sms;
+  USSDInterface m_ussd;
+  
+  PPPIPInterface m_ppp;
+
+  bool m_dongleConnected;
+  bool m_ipInit;
+  bool m_smsInit;
+  bool m_ussdInit;
+  bool m_atOpen;
+};
+
+
+#endif /* VODAFONEK3770_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/at/ATCommandsInterface.cpp	Tue Jun 26 13:44:59 2012 +0000
@@ -0,0 +1,806 @@
+/* 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");
+  }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/at/ATCommandsInterface.h	Tue Jun 26 13:44:59 2012 +0000
@@ -0,0 +1,146 @@
+/* ATCommandsInterface.h */
+/*
+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.
+*/
+
+#ifndef ATCOMMANDSINTERFACE_H_
+#define ATCOMMANDSINTERFACE_H_
+
+#include "core/fwk.h"
+#include "rtos.h"
+
+#define MAX_AT_EVENTS_HANDLERS 8
+
+class ATCommandsInterface;
+
+/** Interface implemented by components handling AT events
+ *
+ */
+class IATEventsHandler
+{
+protected:
+  virtual bool isATCodeHandled(const char* atCode) = 0; //Is this AT code handled
+  virtual void onDispatchStart() = 0;
+  virtual void onDispatchStop() = 0;
+  virtual void onEvent(const char* atCode, const char* evt) = 0;
+  friend class ATCommandsInterface;
+};
+
+/** Interface implemented by components executing complex AT commands
+ *
+ */
+class IATCommandsProcessor
+{
+protected:
+  virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line) = 0;
+  virtual int onNewEntryPrompt(ATCommandsInterface* pInst) = 0;
+  friend class ATCommandsInterface;
+};
+
+#define AT_INPUT_BUF_SIZE 64
+
+//Signals to be sent to the processing thread
+#define AT_SIG_PROCESSING_START 1
+#define AT_SIG_PROCESSING_STOP 2
+//Messages to be sent to the processing thread
+#define AT_CMD_READY 1
+#define AT_TIMEOUT 2
+#define AT_STOP 3
+//Messages to be sent from the processing thread
+#define AT_RESULT_READY 1
+
+/** AT Commands interface class
+ *
+ */
+class ATCommandsInterface : protected IATCommandsProcessor
+{
+public:
+  ATCommandsInterface(IOStream* pStream);
+
+  //Open connection to AT Interface in order to execute command & register/unregister events
+  int open();
+
+  //Initialize AT link
+  int init();
+
+  //Close connection
+  int close();
+  
+  bool isOpen();
+
+  class ATResult
+  {
+  public:
+    enum { AT_OK, AT_ERROR, AT_CONNECT, AT_CMS_ERROR, AT_CME_ERROR } result;
+    int code;
+  };
+
+  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);
+
+  //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 sendData(const char* data);
+
+  static void staticCallback(void const* p);
+private:
+  int tryReadLine();
+  int trySendCommand();
+  int processReadLine();
+  int processEntryPrompt();
+
+  int ATResultToReturnCode(ATResult result); //Helper
+
+  virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line); //Default implementation for simple commands handling
+  virtual int onNewEntryPrompt(ATCommandsInterface* pInst); //Default implementation (just sends Ctrl+Z to exit the prompt)
+
+  void process(); //Processing thread
+
+  IOStream* m_pStream;
+  bool m_open;
+
+  const char* m_transactionCommand;
+  const char* m_transactionData;
+
+  IATCommandsProcessor* m_pTransactionProcessor;
+  ATResult m_transactionResult;
+
+  enum { IDLE, COMMAND_SENT, READING_RESULT, ABORTED } m_transactionState;
+
+  char m_inputBuf[AT_INPUT_BUF_SIZE];
+  int m_inputPos;
+
+  Mutex m_transactionMtx;
+
+  Mail<int,1> m_env2AT;
+  Mail<int,1> m_AT2Env;
+
+  IATEventsHandler* m_eventsHandlers[MAX_AT_EVENTS_HANDLERS];
+
+  Mutex m_processingMtx;
+  Thread m_processingThread;
+
+  Mutex m_eventsMtx;
+};
+
+#endif /* ATCOMMANDSINTERFACE_H_ */
--- a/contrib/vodafone/if/VodafoneK3770.cpp	Fri Jun 08 13:30:06 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,474 +0,0 @@
-/* VodafoneK3770.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__ 4
-#ifndef __MODULE__
-#define __MODULE__ "VodafoneK3770.cpp"
-#endif
-
-#include "core/fwk.h"
-
-#include "VodafoneK3770.h"
-
-VodafoneK3770::VodafoneK3770() : m_dongle(),
-m_stream(m_dongle), m_at(&m_stream),
-m_ppp(&m_stream), m_sms(&m_at), m_ussd(&m_at),
-m_dongleConnected(false), m_ipInit(false), m_smsInit(false), m_atOpen(false)
-{
-
-}
-
-class CREGProcessor : public IATCommandsProcessor
-{
-public:
-  CREGProcessor() : status(STATUS_REGISTERING)
-  {
-
-  }
-  enum REGISTERING_STATUS { STATUS_REGISTERING, STATUS_OK, STATUS_FAILED };
-  REGISTERING_STATUS getStatus()
-  {
-    return status;
-  }
-private:
-  virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
-  {
-    int r;
-    if( sscanf(line, "+CREG: %*d,%d", &r) == 1 )
-    {
-      switch(r)
-      {
-      case 1:
-      case 5:
-        status = STATUS_OK;
-        break;
-      case 0:
-      case 2:
-        status = STATUS_REGISTERING;
-        break;
-      case 3:
-      default:
-        status = STATUS_FAILED;
-        break;
-      }
-    }
-    return OK;
-  }
-  virtual int onNewEntryPrompt(ATCommandsInterface* pInst)
-  {
-    return OK;
-  }
-  volatile REGISTERING_STATUS status;
-};
-
-class COPSProcessor : public IATCommandsProcessor
-{
-public:
-  COPSProcessor() : valid(false)
-  {
-    network[0] = '\0';
-    apn[0] = '\0';
-    bearer[0] = '\0';
-  }
-  char* getNetwork()
-  {
-    return network;
-  }
-  char* getAPN()
-  {
-    return apn;
-  }
-  char* getBearer()
-  {
-    return bearer;
-  }
-  bool isValid()
-  {
-    return valid;
-  }
-private:
-  virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
-  {
-    int networkId;
-    int bearerId;
-    int s = sscanf(line, "+COPS: %*d,%*d,\"%d\",%d", &networkId, &bearerId);
-    if( s == 2 )
-    {
-      switch(networkId)
-      {
-      case 23415:
-        strcpy(network, "Vodafone UK");
-        strcpy(apn, "pp.vodafone.co.uk");
-        valid = true;
-        break;
-      case 20810:
-        strcpy(network, "SFR FR");
-        strcpy(apn, "websfr");
-        valid = true;
-        break;
-      default:
-        break;
-      }
-    }
-    else
-    {
-      return OK;
-    }
-    switch(bearerId)
-    {
-    case 0: strcpy(bearer, "GSM"); break;
-    case 1: strcpy(bearer, "GSM Compact"); break;
-    case 2: strcpy(bearer, "UTRAN"); break;
-    case 3: strcpy(bearer, "GSM w/EGPRS"); break;
-    case 4: strcpy(bearer, "UTRAN w/HSDPA"); break;
-    case 5: strcpy(bearer, "UTRAN w/HSUPA"); break;
-    case 6: strcpy(bearer, "UTRAN w/HSDPA and HSUPA"); break;
-    case 7: strcpy(bearer, "E-UTRAN"); break;
-
-    default:
-      break;
-    }
-    return OK;
-  }
-  virtual int onNewEntryPrompt(ATCommandsInterface* pInst)
-  {
-    return OK;
-  }
-  char network[24];
-  char bearer[24];
-  char apn[24];
-  volatile bool valid;
-};
-
-
-int VodafoneK3770::connect(const char* apn, const char* user, const char* password)
-{
-  if( !m_ipInit )
-  {
-    m_ipInit = true;
-    m_ppp.init();
-  }
-  m_ppp.setup(user, password);
-
-  int ret = init();
-  if(ret)
-  {
-    return ret;
-  }
-
-  m_smsInit = false; //SMS status reset
-  m_ussdInit = false; //USSD status reset
-
-  ATCommandsInterface::ATResult result;
-
-#if 0
-  //Get network info & select corresponding APN
-  COPSProcessor copsProcessor;
-  DBG("Get network info & select APN from DB");
-  ret = m_at.execute("AT+COPS=,2;+COPS?", &copsProcessor, &result); //Configure to get operator's info in numeric code & get operator's id
-  DBG("Result of command: Err code=%d", ret);
-  DBG("ATResult: AT return=%d (code %d)", result.result, result.code);
-
-  if(!copsProcessor.isValid())
-  {
-    WARN("Connected to an unknown network, try to connect with default parameters");
-    DBG("Connected with %s", copsProcessor.getBearer());
-  }
-  else
-  {
-    DBG("Connected to %s with %s", copsProcessor.getNetwork(), copsProcessor.getBearer());
-    char cmd[48];
-    sprintf(cmd, "AT+CGDCONT=1,\"IP\",\"%s\"", copsProcessor.getAPN());
-    ret = m_at.executeSimple(cmd, &result);
-    DBG("Result of command: Err code=%d", ret);
-    DBG("ATResult: AT return=%d (code %d)", result.result, result.code);
-    DBG("APN set to %s", copsProcessor.getAPN());
-  }
-  #else
-  if(apn != NULL)
-  {
-    char cmd[48];
-    sprintf(cmd, "AT+CGDCONT=1,\"IP\",\"%s\"", apn);
-    ret = m_at.executeSimple(cmd, &result);
-    DBG("Result of command: Err code=%d", ret);
-    DBG("ATResult: AT return=%d (code %d)", result.result, result.code);
-    DBG("APN set to %s", apn);
-  }
-  #endif
-
-
-  //Connect
-  DBG("Connecting");
-  ret = m_at.executeSimple("ATDT *99#", &result);
-  DBG("Result of command: Err code=%d", ret);
-  DBG("ATResult: AT return=%d (code %d)", result.result, result.code);
-  m_at.close(); // Closing AT parser
-  m_atOpen = false; //Will need to be reinitialized afterwards
-
-  DBG("AT Parser closed");
-  if( (ret!=NET_MOREINFO) || (result.result != ATCommandsInterface::ATResult::AT_CONNECT))
-  {
-    ERR("Could not connect");
-    return ret; //Could not connect
-  }
-  DBG("Connecting PPP");
-
-  ret = m_ppp.connect();
-  DBG("Result of connect: Err code=%d", ret);
-  return ret;
-}
-
-
-int VodafoneK3770::disconnect()
-{
-  DBG("Disconnecting from PPP");
-  int ret = m_ppp.disconnect();
-  if(ret)
-  {
-    ERR("Disconnect returned %d, still trying to disconnect", ret);
-  }
-
-  //Ugly but leave dongle time to recover
-  Thread::wait(500);
-
-  ATCommandsInterface::ATResult result;
-  DBG("Starting AT thread");
-  ret = m_at.open();
-  if(ret)
-  {
-    return ret;
-  }
-
-  DBG("Trying to hangup");
-
-#if 0 //Does not appear to work
-  int tries = 10;
-  do
-  {
-    ret = m_at.executeSimple("+++", &result, 1000);
-    DBG("Result of command: Err code=%d\n", ret);
-    DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code);
-  } while(tries-- && ret);
-  if(!ret)
-  {
-    ret = m_at.executeSimple("ATH", &result);
-    DBG("Result of command: Err code=%d\n", ret);
-    DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code);
-  }
-#endif
-
-  //Reinit AT parser
-  ret = m_at.init();
-  DBG("Result of command: Err code=%d\n", ret);
-  if(ret)
-  {
-    m_at.close(); // Closing AT parser
-    DBG("AT Parser closed, could not complete disconnection");
-    return NET_TIMEOUT;
-  }
-
-  m_at.close(); // Closing AT parser
-  DBG("AT Parser closed");
-  return OK;
-}
-
-int VodafoneK3770::sendSM(const char* number, const char* message)
-{
-  int ret = init();
-  if(ret)
-  {
-    return ret;
-  }
-
-  if(!m_smsInit)
-  {
-    ret = m_sms.init();
-    if(ret)
-    {
-      return ret;
-    }
-    m_smsInit = true;
-  }
-
-  ret = m_sms.send(number, message);
-  if(ret)
-  {
-    return ret;
-  }
-
-  return OK;
-}
-
-int VodafoneK3770::getSM(char* number, char* message, size_t maxLength)
-{
-  int ret = init();
-  if(ret)
-  {
-    return ret;
-  }
-
-  if(!m_smsInit)
-  {
-    ret = m_sms.init();
-    if(ret)
-    {
-      return ret;
-    }
-    m_smsInit = true;
-  }
-
-  ret = m_sms.get(number, message, maxLength);
-  if(ret)
-  {
-    return ret;
-  }
-
-  return OK;
-}
-
-int VodafoneK3770::getSMCount(size_t* pCount)
-{
-  int ret = init();
-  if(ret)
-  {
-    return ret;
-  }
-
-  if(!m_smsInit)
-  {
-    ret = m_sms.init();
-    if(ret)
-    {
-      return ret;
-    }
-    m_smsInit = true;
-  }
-
-  ret = m_sms.getCount(pCount);
-  if(ret)
-  {
-    return ret;
-  }
-
-  return OK;
-}
-
-int VodafoneK3770::sendUSSD(const char* command, char* result, size_t maxLength)
-{
-  int ret = init();
-  if(ret)
-  {
-    return ret;
-  }
-
-  if(!m_ussdInit)
-  {
-    ret = m_ussd.init();
-    if(ret)
-    {
-      return ret;
-    }
-    m_ussdInit = true;
-  }
-
-  ret = m_ussd.send(command, result, maxLength);
-  if(ret)
-  {
-    return ret;
-  }
-
-  return OK;
-}
-
-ATCommandsInterface* VodafoneK3770::getATCommandsInterface()
-{
-  return &m_at;
-}
-
-int VodafoneK3770::init()
-{
-  if( !m_dongleConnected )
-  {
-    m_dongleConnected = true;
-    while( !m_dongle.connected() )
-    {
-      m_dongle.tryConnect();
-      Thread::wait(10);
-    }
-  }
-
-  if(m_atOpen)
-  {
-    return OK;
-  }
-
-  DBG("Starting AT thread if needed");
-  int ret = m_at.open();
-  if(ret)
-  {
-    return ret;
-  }
-
-  DBG("Sending initialisation commands");
-  ret = m_at.init();
-  if(ret)
-  {
-    return ret;
-  }
-
-  DBG("Configuring unsolicited result codes support properly");
-  //Configuring port
-  ret = m_at.executeSimple("AT^CURC=0;^PORTSEL=1", NULL); //Huawei-specific, not 3GPP-compliant
-  if(ret != OK)
-  {
-    return NET_PROTOCOL;
-  }
-
-  ATCommandsInterface::ATResult result;
-
-  //Wait for network registration
-  CREGProcessor cregProcessor;
-  do
-  {
-    DBG("Waiting for network registration");
-    ret = m_at.execute("AT+CREG?", &cregProcessor, &result);
-    DBG("Result of command: Err code=%d\n", ret);
-    DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code);
-    if(cregProcessor.getStatus() == CREGProcessor::STATUS_REGISTERING)
-    {
-      Thread::wait(3000);
-    }
-  } while(cregProcessor.getStatus() == CREGProcessor::STATUS_REGISTERING);
-  if(cregProcessor.getStatus() == CREGProcessor::STATUS_FAILED)
-  {
-    ERR("Registration denied");
-    return NET_AUTH;
-  }
-
-  m_atOpen = true;
-
-  return OK;
-}
-
-
-
--- a/contrib/vodafone/if/VodafoneK3770.h	Fri Jun 08 13:30:06 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,113 +0,0 @@
-/* VodafoneK3770.h */
-/*
-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.
-*/
-
-#ifndef VODAFONEK3770_H_
-#define VODAFONEK3770_H_
-
-#include "core/fwk.h"
-
-#include "USB3GModule/WANDongle.h"
-#include "drv/at/ATCommandsInterface.h"
-#include "drv/serial/usb/USBSerialStream.h"
-#include "if/ip/PPPIPInterface.h"
-#include "if/sms/SMSInterface.h"
-#include "if/ussd/USSDInterface.h"
-
-/** Vodafone K3770 dongle
- */
-class VodafoneK3770
-{
-public:
-  /** Create Vodafone K3770 dongle API instance
-
-   */
-  VodafoneK3770();
-
-  //Internet-related functions
-
-  /** Open a 3G internet connection
-      @return 0 on success, error code on failure
-  */
-  int connect(const char* apn = NULL, const char* user = NULL, const char* password = NULL);
-
-  /** Close the internet connection
-     @return 0 on success, error code on failure
-  */
-  int disconnect();
-
-
-  /** Send a SM
-     @param number The receiver's phone number
-     @param message The message to send
-     @return 0 on success, error code on failure
-   */
-  int sendSM(const char* number, const char* message);
-
-
-  /** Receive a SM
-     @param number Pointer to a buffer to store the sender's phone number (must be at least 17 characters-long, including the sapce for the null-terminating char)
-     @param message Pointer to a buffer to store the the incoming message
-     @param maxLength Maximum message length that can be stored in buffer (including null-terminating character)
-     @return 0 on success, error code on failure
-   */
-  int getSM(char* number, char* message, size_t maxLength);
-
-  /** Get the number of SMs in the incoming box
-     @param pCount pointer to store the number of unprocessed SMs on
-     @return 0 on success, error code on failure
-   */
-  int getSMCount(size_t* pCount);
-
-  /** Send a USSD command & wait for its result
-    @param command The command to send
-    @param result Buffer in which to store the result
-    @param maxLength Maximum result length that can be stored in buffer (including null-terminating character)
-    @return 0 on success, error code on failure
-  */
-  int sendUSSD(const char* command, char* result, size_t maxLength);
-
-  /** Get the ATCommandsInterface instance
-     @return Pointer to the ATCommandsInterface instance
-   */
-  ATCommandsInterface* getATCommandsInterface();
-
-protected:
-  int init();
-
-private:
-  WANDongle m_dongle;
-  USBSerialStream m_stream;
-  ATCommandsInterface m_at;
-  PPPIPInterface m_ppp;
-  SMSInterface m_sms;
-  USSDInterface m_ussd;
-
-  bool m_dongleConnected;
-  bool m_ipInit;
-  bool m_smsInit;
-  bool m_ussdInit;
-  bool m_atOpen;
-};
-
-
-#endif /* VODAFONEK3770_H_ */
--- a/contrib/vodafone/if/vodafone/VodafoneManager.h	Fri Jun 08 13:30:06 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,20 +0,0 @@
-/*
- * VodafoneManager.h
- *
- *  Created on: 16 déc. 2011
- *      Author: Donatien
- */
-
-#ifndef VODAFONEMANAGER_H_
-#define VODAFONEMANAGER_H_
-
-#include "core/fwk.h"
-#include "if/ussd/USSDInterface.h"
-
-class VodafoneManager : protected USSDInterface
-{
-
-
-};
-
-#endif /* VODAFONEMANAGER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ip/PPPIPInterface.cpp	Tue Jun 26 13:44:59 2012 +0000
@@ -0,0 +1,269 @@
+/* PPPIPInterface.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 //Maximum verbosity
+#ifndef __MODULE__
+#define __MODULE__ "PPPIPInterface.cpp"
+#endif
+
+#include "core/fwk.h"
+#include "rtos.h"
+
+#include "PPPIPInterface.h"
+
+extern "C" {
+#include "lwip/ip_addr.h"
+#include "lwip/inet.h"
+#include "netif/ppp/ppp.h"
+}
+
+#if NET_PPP
+
+PPPIPInterface::PPPIPInterface(IOStream* pStream) : LwIPInterface(), m_linkStatusSphre(1), m_pppErrCode(0), m_pStream(pStream), m_streamAvail(true), m_pppd(-1)
+{
+  m_linkStatusSphre.wait();
+}
+
+/*virtual*/ PPPIPInterface::~PPPIPInterface()
+{
+
+}
+
+/*virtual*/ int PPPIPInterface::init() //Init PPP-specific stuff, create the right bindings, etc
+{
+  DBG("Initializing LwIP");
+  LwIPInterface::init(); //Init LwIP, NOT including PPP
+  DBG("Initializing PPP");
+  pppInit();
+  DBG("Done");
+  return OK;
+}
+
+int PPPIPInterface::setup(const char* user, const char* pw)
+{
+  DBG("Configuring PPP authentication method");
+  pppSetAuth(PPPAUTHTYPE_ANY, user, pw);
+  DBG("Done");
+  return OK;
+}
+
+/*virtual*/ int PPPIPInterface::connect()
+{
+  DBG("Trying to connect with PPP");
+  m_linkStatusSphre.wait(0);
+  if((m_pppd != -1) && (m_pppErrCode == 0)) //Already connected
+  {
+    return NET_INVALID;
+  }
+  int ret = pppOverSerialOpen(this, PPPIPInterface::linkStatusCb, this);
+  if(ret < 0)
+  {
+    switch(ret)
+    {
+    case PPPERR_OPEN:
+    default:
+      return NET_FULL; //All available resources are already used
+    }
+  }
+  m_pppd = ret; //PPP descriptor
+  m_linkStatusSphre.wait(); //Block indefinitely; there should be a timeout there
+  if(m_pppErrCode != PPPERR_NONE)
+  {
+    m_pppd = -1;
+  }
+  switch(m_pppErrCode)
+  {
+  case PPPERR_NONE: //Connected OK
+    return OK;
+  case PPPERR_CONNECT: //Connection lost
+    return NET_INTERRUPTED;
+  case PPPERR_AUTHFAIL: //Authentication failed
+    return NET_AUTH;
+  case PPPERR_PROTOCOL: //Protocol error
+    return NET_PROTOCOL;
+  default:
+    return NET_UNKNOWN;
+  }
+}
+
+/*virtual*/ int PPPIPInterface::disconnect()
+{
+  int ret = m_linkStatusSphre.wait(0);
+  if(ret > 0) //Already disconnected?
+  {
+    m_pppd = -1; //Discard PPP descriptor
+    switch(m_pppErrCode)
+      {
+      case PPPERR_CONNECT: //Connection terminated
+      case PPPERR_AUTHFAIL: //Authentication failed
+      case PPPERR_PROTOCOL: //Protocol error
+      case PPPERR_USER:
+        return OK;
+      default:
+        return NET_UNKNOWN;
+      }
+  }
+  else
+  {
+    if(m_pppd == -1)
+    {
+      return NET_INVALID;
+    }
+    pppClose(m_pppd);
+    do
+    {
+      m_linkStatusSphre.wait(); //Block indefinitely; there should be a timeout there
+      DBG("Received PPP err code %d", m_pppErrCode);
+    } while(m_pppErrCode != PPPERR_USER);
+    m_pppd = -1; //Discard PPP descriptor
+  }
+  return OK;
+}
+
+/*static*/ void PPPIPInterface::linkStatusCb(void *ctx, int errCode, void *arg) //PPP link status
+{
+  PPPIPInterface* pIf = (PPPIPInterface*)ctx;
+  struct ppp_addrs* addrs = (struct ppp_addrs*) arg;
+
+  switch(errCode)
+  {
+  case PPPERR_NONE:
+    WARN("Connected via PPP.");
+    DBG("Local IP address: %s", inet_ntoa(addrs->our_ipaddr));
+    DBG("Netmask: %s", inet_ntoa(addrs->netmask));
+    DBG("Remote IP address: %s", inet_ntoa(addrs->his_ipaddr));
+    DBG("Primary DNS: %s", inet_ntoa(addrs->dns1));
+    DBG("Secondary DNS: %s", inet_ntoa(addrs->dns2));
+    setConnected(true);
+    setIPAddress(inet_ntoa(addrs->our_ipaddr));
+    break;
+  case PPPERR_CONNECT: //Connection lost
+    WARN("Connection lost/terminated");
+    setConnected(false);
+    break;
+  case PPPERR_AUTHFAIL: //Authentication failed
+    WARN("Authentication failed");
+    setConnected(false);
+    break;
+  case PPPERR_PROTOCOL: //Protocol error
+    WARN("Protocol error");
+    setConnected(false);
+    break;
+  case PPPERR_USER:
+    WARN("Disconnected by user");
+    setConnected(false);
+    break;
+  default:
+    WARN("Unknown error (%d)", errCode);
+    setConnected(false);
+    break;
+  }
+
+  pIf->m_linkStatusSphre.wait(0); //If previous event has not been handled, "delete" it now
+  pIf->m_pppErrCode = errCode;
+  pIf->m_linkStatusSphre.release();
+}
+
+//LwIP PPP implementation
+extern "C"
+{
+
+/**
+ * Writes to the serial device.
+ *
+ * @param fd serial device handle
+ * @param data pointer to data to send
+ * @param len length (in bytes) of data to send
+ * @return number of bytes actually sent
+ *
+ * @note This function will block until all data can be sent.
+ */
+u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len)
+{
+  DBG("sio_write");
+  PPPIPInterface* pIf = (PPPIPInterface*)fd;
+  int ret;
+  if(!pIf->m_streamAvail) //If stream is not available (it is a shared resource) don't go further
+  {
+    return 0;
+  }
+  ret = pIf->m_pStream->write(data, len, osWaitForever); //Blocks until all data is sent or an error happens
+  if(ret != OK)
+  {
+    return 0;
+  }
+  return len;
+}
+
+/**
+ * Reads from the serial device.
+ *
+ * @param fd serial device handle
+ * @param data pointer to data buffer for receiving
+ * @param len maximum length (in bytes) of data to receive
+ * @return number of bytes actually received - may be 0 if aborted by sio_read_abort
+ *
+ * @note This function will block until data can be received. The blocking
+ * can be cancelled by calling sio_read_abort().
+ */
+u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len)
+{
+  DBG("sio_read");
+  PPPIPInterface* pIf = (PPPIPInterface*)fd;
+  int ret;
+  size_t readLen;
+  if(!pIf->m_streamAvail) //If stream is not available (it is a shared resource) don't go further
+  {
+    WARN("EXIT NOT AVAIL");
+    return 0;
+  }
+  ret = pIf->m_pStream->read(data, &readLen, len, osWaitForever); //Blocks until some data is received or an error happens
+  if(ret != OK)
+  {
+    return 0;
+  }
+  DBG("ret");
+  return readLen;
+}
+
+/**
+ * Aborts a blocking sio_read() call.
+ *
+ * @param fd serial device handle
+ */
+void sio_read_abort(sio_fd_t fd)
+{
+  DBG("sio_read_abort");
+  PPPIPInterface* pIf = (PPPIPInterface*)fd;
+  if(!pIf->m_streamAvail) //If stream is not available (it is a shared resource) don't go further
+  {
+    return;
+  }
+  pIf->m_pStream->abortRead();
+  DBG("ret");
+}
+
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ip/PPPIPInterface.h	Tue Jun 26 13:44:59 2012 +0000
@@ -0,0 +1,67 @@
+/* PPPIPInterface.h */
+/*
+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.
+*/
+
+#ifndef PPPIPINTERFACE_H_
+#define PPPIPINTERFACE_H_
+
+#include "core/fwk.h"
+
+#include "LwIPInterface.h"
+
+#include "lwip/sio.h"
+
+namespace rtos {
+class Semaphore;
+}
+using namespace rtos;
+
+/** Interface using PPP to connect to an IP-based network
+ *
+ */
+class PPPIPInterface : public LwIPInterface
+{
+public:
+    PPPIPInterface(IOStream* pStream);
+    virtual ~PPPIPInterface();
+
+    int init(); //Init PPP-specific stuff, create the right bindings, etc
+    int setup(const char* user, const char* pw); //Setup authentication
+    virtual int connect();
+    virtual int disconnect();
+
+private:
+    static void linkStatusCb(void *ctx, int errCode, void *arg); //PPP link status
+    Semaphore m_linkStatusSphre;
+    int m_pppErrCode;
+
+    IOStream* m_pStream; //Serial stream
+    bool m_streamAvail;
+
+    int m_pppd;
+
+    friend u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len);
+    friend u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len);
+    friend void sio_read_abort(sio_fd_t fd);
+};
+
+#endif /* PPPIPINTERFACE_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwipopts.h	Tue Jun 26 13:44:59 2012 +0000
@@ -0,0 +1,45 @@
+/* lwipopts.h */
+/*
+ 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.
+ */
+
+#ifndef LWIPOPTS_H_
+#define LWIPOPTS_H_
+ 
+#include "lwipopts_common.h" //Get common options
+
+///PPP Options
+
+#define TCP_SND_BUF                     (3 * 536)
+#define TCP_WND                         (2 * 536)
+
+#define LWIP_ARP 0
+
+#define PPP_SUPPORT 1
+#define CHAP_SUPPORT                    1
+#define PAP_SUPPORT                     1
+#define PPP_THREAD_STACKSIZE            4*192
+#define PPP_THREAD_PRIO 0
+
+#define MAXNAMELEN                      64     /* max length of hostname or name for auth */
+#define MAXSECRETLEN                    64
+
+#endif /* LWIPOPTS_H_ */
\ No newline at end of file
--- 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");
-  }
-}
-
--- a/main/drv/at/ATCommandsInterface.h	Fri Jun 08 13:30:06 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,146 +0,0 @@
-/* ATCommandsInterface.h */
-/*
-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.
-*/
-
-#ifndef ATCOMMANDSINTERFACE_H_
-#define ATCOMMANDSINTERFACE_H_
-
-#include "core/fwk.h"
-#include "rtos.h"
-
-#define MAX_AT_EVENTS_HANDLERS 8
-
-class ATCommandsInterface;
-
-/** Interface implemented by components handling AT events
- *
- */
-class IATEventsHandler
-{
-protected:
-  virtual bool isATCodeHandled(const char* atCode) = 0; //Is this AT code handled
-  virtual void onDispatchStart() = 0;
-  virtual void onDispatchStop() = 0;
-  virtual void onEvent(const char* atCode, const char* evt) = 0;
-  friend class ATCommandsInterface;
-};
-
-/** Interface implemented by components executing complex AT commands
- *
- */
-class IATCommandsProcessor
-{
-protected:
-  virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line) = 0;
-  virtual int onNewEntryPrompt(ATCommandsInterface* pInst) = 0;
-  friend class ATCommandsInterface;
-};
-
-#define AT_INPUT_BUF_SIZE 64
-
-//Signals to be sent to the processing thread
-#define AT_SIG_PROCESSING_START 1
-#define AT_SIG_PROCESSING_STOP 2
-//Messages to be sent to the processing thread
-#define AT_CMD_READY 1
-#define AT_TIMEOUT 2
-#define AT_STOP 3
-//Messages to be sent from the processing thread
-#define AT_RESULT_READY 1
-
-/** AT Commands interface class
- *
- */
-class ATCommandsInterface : protected IATCommandsProcessor
-{
-public:
-  ATCommandsInterface(IOStream* pStream);
-
-  //Open connection to AT Interface in order to execute command & register/unregister events
-  int open();
-
-  //Initialize AT link
-  int init();
-
-  //Close connection
-  int close();
-  
-  bool isOpen();
-
-  class ATResult
-  {
-  public:
-    enum { AT_OK, AT_ERROR, AT_CONNECT, AT_CMS_ERROR, AT_CME_ERROR } result;
-    int code;
-  };
-
-  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);
-
-  //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 sendData(const char* data);
-
-  static void staticCallback(void const* p);
-private:
-  int tryReadLine();
-  int trySendCommand();
-  int processReadLine();
-  int processEntryPrompt();
-
-  int ATResultToReturnCode(ATResult result); //Helper
-
-  virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line); //Default implementation for simple commands handling
-  virtual int onNewEntryPrompt(ATCommandsInterface* pInst); //Default implementation (just sends Ctrl+Z to exit the prompt)
-
-  void process(); //Processing thread
-
-  IOStream* m_pStream;
-  bool m_open;
-
-  const char* m_transactionCommand;
-  const char* m_transactionData;
-
-  IATCommandsProcessor* m_pTransactionProcessor;
-  ATResult m_transactionResult;
-
-  enum { IDLE, COMMAND_SENT, READING_RESULT, ABORTED } m_transactionState;
-
-  char m_inputBuf[AT_INPUT_BUF_SIZE];
-  int m_inputPos;
-
-  Mutex m_transactionMtx;
-
-  Mail<int,1> m_env2AT;
-  Mail<int,1> m_AT2Env;
-
-  IATEventsHandler* m_eventsHandlers[MAX_AT_EVENTS_HANDLERS];
-
-  Mutex m_processingMtx;
-  Thread m_processingThread;
-
-  Mutex m_eventsMtx;
-};
-
-#endif /* ATCOMMANDSINTERFACE_H_ */
--- a/main/drv/serial/io/IOSerialStream.cpp	Fri Jun 08 13:30:06 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,257 +0,0 @@
-/* IOSerialStream.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__ 0 //Maximum verbosity
-#ifndef __MODULE__
-#define __MODULE__ "IOSerialStream.cpp"
-#endif
-
-#include "core/fwk.h"
-
-#include <stdio.h>
-
-#include "IOSerialStream.h"
-
-IOSerialStream::IOSerialStream(mbed::Serial& serial) : m_serial(serial), m_serialTxFifoEmpty(true),
-m_availableSphre(1), m_spaceSphre(1), m_inBuf(), m_outBuf()
-{
-  m_availableSphre.wait();
-  m_spaceSphre.wait();
-  //Attach interrupts
-  m_serial.attach(this, &IOSerialStream::readable, mbed::Serial::RxIrq);
-  m_serial.attach(this, &IOSerialStream::writeable, mbed::Serial::TxIrq);
-}
-
-/*virtual*/ IOSerialStream::~IOSerialStream()
-{
-  m_serial.attach(NULL, mbed::Serial::RxIrq);
-  m_serial.attach(NULL, mbed::Serial::TxIrq);
-}
-
-//0 for non-blocking (returns immediately), osWaitForever for infinite blocking
-/*virtual*/ int IOSerialStream::read(uint8_t* buf, size_t* pLength, size_t maxLength, uint32_t timeout/*=osWaitForever*/)
-{
-  DBG("Trying to read at most %d chars", maxLength);
-  int ret = waitAvailable(timeout);
-  if(ret)
-  {
-    WARN("Error %d while waiting for incoming data");
-    return ret;
-  }
-  int readLen = MIN( available(), maxLength );
-  *pLength = readLen;
-  setupReadableISR(false);
-  while(readLen--)
-  {
-    m_inBuf.dequeue(buf);
-    buf++;
-  }
-  setupReadableISR(true);
-  DBG("Read %d chars successfully", *pLength);
-  return OK;
-}
-
-/*virtual*/ size_t IOSerialStream::available()
-{
-  setupReadableISR(false); //m_inBuf.available() is not reentrant
-  size_t len = m_inBuf.available();
-  setupReadableISR(true);
-  return len;
-}
-
-/*virtual*/ int IOSerialStream::waitAvailable(uint32_t timeout/*=osWaitForever*/) //Wait for data to be available
-{
-  int ret;
-  if(available()) //Is data already available?
-  {
-    m_availableSphre.wait(0); //Clear the queue as data is available
-    return OK;
-  }
-
-  DBG("Waiting for data availability %d ms (-1 is infinite)", timeout);
-  ret = m_availableSphre.wait(timeout); //Wait for data to arrive or for abort
-  if(ret <= 0)
-  {
-    DBG("Timeout");
-    return NET_TIMEOUT;
-  }
-  if(!available()) //Even if abort has been called, return that data is available
-  {
-    DBG("Aborted");
-    return NET_INTERRUPTED;
-  }
-  DBG("Finished waiting");
-  m_availableSphre.wait(0); //Clear the queue as data is available
-  return OK;
-}
-
-/*virtual*/ int IOSerialStream::abortRead() //Abort current reading (or waiting) operation
-{
-  if( !available() ) //If there is data pending, no need to abort
-  {
-    m_availableSphre.release(); //Force exiting the waiting state; kludge to pass a RC directly
-  }
-  else
-  {
-    DBG("Serial is readable"); ;
-  }
-  return OK;
-}
-
-void IOSerialStream::setupReadableISR(bool en)
-{
-  if(en)
-  {
-    ((LPC_UART_TypeDef *)(UART_3))->IER |= 1 << 0;
-  }
-  else
-  {
-    ((LPC_UART_TypeDef *)(UART_3))->IER &= ~(1 << 0);
-  }
-}
-
-void IOSerialStream::readable() //Callback from m_serial when new data is available
-{
-  do
-  {
-    m_inBuf.queue(((LPC_UART_TypeDef *)UART_3)->RBR); //FIXME mbed libraries this is an awful kludge
-  } while(m_serial.readable());
-  m_availableSphre.release(); //Force exiting the waiting state
-}
-
-//0 for non-blocking (returns immediately), osWaitForever for infinite blocking
-/*virtual*/ int IOSerialStream::write(uint8_t* buf, size_t length, uint32_t timeout/*=osWaitForever*/)
-{
-  DBG("Trying to write %d chars", length);
-  int ret = waitSpace(timeout);
-  if(ret)
-  {
-    WARN("Error %d while waiting for space");
-    return ret;
-  }
-  DBG("Writing %d chars", length);
-  setupWriteableISR(false);
-  while(length)
-  {
-    m_outBuf.queue(*buf);
-    buf++;
-    length--;
-    if(length && !space())
-    {
-      DBG("Waiting to write remaining %d chars", length);
-      setupWriteableISR(true);
-      ret = waitSpace(timeout);
-      if(ret)
-      {
-        WARN("Error %d while waiting for space");
-        return ret;
-      }
-      setupWriteableISR(false);
-    }
-  }
-  //If m_serial tx fifo is empty we need to manually tx a byte in order to trigger the interrupt
-  if( m_outBuf.available() && m_serialTxFifoEmpty )
-  {
-    m_serialTxFifoEmpty = false;
-    uint8_t c;
-    m_outBuf.dequeue(&c);
-    //m_serial.putc((char)c);
-    ((LPC_UART_TypeDef *)UART_3)->THR = c; //FIXME awful kludge
-  }
-  setupWriteableISR(true);
-  DBG("Write successful");
-  return OK;
-}
-
-/*virtual*/ size_t IOSerialStream::space()
-{
-  setupWriteableISR(false); //m_outBuf.available() is not reentrant
-  size_t len = CIRCBUF_SIZE - m_outBuf.available();
-  setupWriteableISR(true);
-  return len;
-}
-
-/*virtual*/ int IOSerialStream::waitSpace(uint32_t timeout/*=osWaitForever*/) //Wait for space to be available
-{
-  int ret;
-  if(space()) //Is still space already left?
-  {
-    m_spaceSphre.wait(0); //Clear the queue as space is available
-    return OK;
-  }
-
-  DBG("Waiting for data space %d ms (-1 is infinite)", timeout);
-  ret = m_spaceSphre.wait(timeout); //Wait for space to be made or for abort
-  if(ret <= 0)
-  {
-    DBG("Timeout");
-    return NET_TIMEOUT;
-  }
-  if(!space()) //Even if abort has been called, return that space is available
-  {
-    DBG("Aborted");
-    return NET_INTERRUPTED;
-  }
-  m_spaceSphre.wait(0); //Clear the queue as space is available
-  return OK;
-}
-
-/*virtual*/ int IOSerialStream::abortWrite() //Abort current writing (or waiting) operation
-{
-  if( !space() ) //If there is space left, no need to abort
-  {
-    m_spaceSphre.release(); //Force exiting the waiting state
-  }
-  return OK;
-}
-
-void IOSerialStream::setupWriteableISR(bool en)
-{
-  if(en)
-  {
-    ((LPC_UART_TypeDef *)(UART_3))->IER |= 1 << 1;
-  }
-  else
-  {
-    ((LPC_UART_TypeDef *)(UART_3))->IER &= ~(1 << 1);
-  }
-}
-
-void IOSerialStream::writeable() //Callback from m_serial when new space is available
-{
-  if(m_outBuf.isEmpty())
-  {
-    m_serialTxFifoEmpty = true;
-  }
-  else
-  {
-    while(m_serial.writeable() && !m_outBuf.isEmpty())
-    {
-      uint8_t c;
-      m_outBuf.dequeue(&c);
-      //m_serial.putc((char)c);
-      ((LPC_UART_TypeDef *)UART_3)->THR = c; //FIXME awful kludge
-    }
-  }
-  m_spaceSphre.release(); //Force exiting the waiting state
-}
--- a/main/drv/serial/io/IOSerialStream.h	Fri Jun 08 13:30:06 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/* IOSerialStream.h */
-/*
-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.
-*/
-
-#ifndef IOSERIALSTREAM_H_
-#define IOSERIALSTREAM_H_
-
-#include "core/fwk.h"
-
-#include "Serial.h"
-
-#include "rtos.h"
-#include "core/MtxCircBuffer.h"
-
-/** Input Serial Stream for physical serial interfaces (UART...)
-This class is not thread-safe, except for the *Abort() methods that can be called by any thread/ISR
-*/
-#define CIRCBUF_SIZE 255
-class IOSerialStream : public IOStream
-{
-public:
-  IOSerialStream(mbed::Serial& serial);
-  /*virtual*/ ~IOSerialStream();
-
-  //0 for non-blocking (returns immediately), osWaitForever for infinite blocking
-  virtual int read(uint8_t* buf, size_t* pLength, size_t maxLength, uint32_t timeout=osWaitForever);
-  virtual size_t available();
-  virtual int waitAvailable(uint32_t timeout=osWaitForever); //Wait for data to be available
-  virtual int abortRead(); //Abort current reading (or waiting) operation
-
-
-  //0 for non-blocking (returns immediately), osWaitForever for infinite blocking
-  virtual int write(uint8_t* buf, size_t length, uint32_t timeout=osWaitForever);
-  virtual size_t space();
-  virtual int waitSpace(uint32_t timeout=osWaitForever); //Wait for space to be available
-  virtual int abortWrite(); //Abort current writing (or waiting) operation
-
-private:
-
-  mbed::Serial& m_serial;
-  volatile bool m_serialTxFifoEmpty;
-
-  void setupReadableISR(bool en);
-  void readable(); //Callback from m_serial when new data is available
-
-  Semaphore m_availableSphre; //Used for signalling
-
-  void setupWriteableISR(bool en);
-  void writeable(); //Callback from m_serial when new space is available
-
-  Semaphore m_spaceSphre; //Used for signalling
-
-  MtxCircBuffer<uint8_t, CIRCBUF_SIZE + 1> m_inBuf;
-  MtxCircBuffer<uint8_t, CIRCBUF_SIZE + 1> m_outBuf;
-
-};
-
-#endif /* IOSERIALSTREAM_H_ */
--- a/main/drv/serial/usb/USBSerialStream.cpp	Fri Jun 08 13:30:06 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,237 +0,0 @@
-/* USBSerialStream.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__ 0 //Maximum verbosity
-#ifndef __MODULE__
-#define __MODULE__ "USBSerialStream.cpp"
-#endif
-
-#include "core/fwk.h"
-
-#include <stdio.h>
-
-#include "USBSerialStream.h"
-
-
-USBSerialStream::USBSerialStream(IUSBHostSerial& serial) : m_serial(serial), m_serialTxFifoEmpty(true),
-m_availableSphre(1), m_spaceSphre(1), m_inBuf()
-{
-  m_availableSphre.wait();
-  m_spaceSphre.wait();
-  //Attach interrupts
-  m_serial.attach(this);
-}
-
-/*virtual*/ USBSerialStream::~USBSerialStream()
-{
-  m_serial.attach(NULL);
-}
-
-//0 for non-blocking (returns immediately), -1 for infinite blocking
-/*virtual*/ int USBSerialStream::read(uint8_t* buf, size_t* pLength, size_t maxLength, uint32_t timeout/*=osWaitForever*/)
-{
-  DBG("Trying to read at most %d chars", maxLength);
-  int ret = waitAvailable(timeout);
-  if(ret)
-  {
-    WARN("Error %d while waiting for incoming data", ret);
-    return ret;
-  }
-  int readLen = MIN( available(), maxLength );
-  *pLength = readLen;
-
-  setupReadableISR(false);
-  while(readLen--)
-  {
-    m_inBuf.dequeue(buf);
-    buf++;
-  }
-  setupReadableISR(true);
-  DBG("Read %d chars successfully", *pLength);
-  return OK;
-}
-
-/*virtual*/ size_t USBSerialStream::available()
-{
-  setupReadableISR(false); //m_inBuf.available() is not reentrant
-  size_t len = m_inBuf.available();
-  setupReadableISR(true);
-  return len;
-}
-
-/*virtual*/ int USBSerialStream::waitAvailable(uint32_t timeout/*=osWaitForever*/) //Wait for data to be available
-{
-  int ret;
-  if(available()) //Is data already available?
-  {
-    m_availableSphre.wait(0); //Clear the queue as data is available
-    return OK;
-  }
-
-  DBG("Waiting for data availability %d ms (-1 is infinite)", timeout);
-  ret = m_availableSphre.wait(timeout); //Wait for data to arrive or for abort
-  if(ret <= 0)
-  {
-    DBG("Timeout");
-    return NET_TIMEOUT;
-  }
-  if(!m_inBuf.available()) //Even if abort has been called, return that data is available
-  {
-    DBG("Aborted");
-    return NET_INTERRUPTED;
-  }
-  DBG("Finished waiting");
-  m_availableSphre.wait(0); //Clear the queue as data is available
-  return OK;
-}
-
-/*virtual*/ int USBSerialStream::abortRead() //Abort current reading (or waiting) operation
-{
-  if( /*!available()*/true ) //If there is data pending, no need to abort
-  {
-    m_availableSphre.release(); //Force exiting the waiting state
-  }
-  else
-  {
-    DBG("Serial is readable"); ;
-  }
-  return OK;
-}
-
-void USBSerialStream::setupReadableISR(bool en)
-{
-  m_serial.setupIrq(en, IUSBHostSerial::RxIrq);
-}
-
-void USBSerialStream::readable() //Callback from m_serial when new data is available
-{
-  while(m_serial.readable())
-  {
-    m_inBuf.queue(m_serial.getc());
-  }
-  m_serial.readPacket(); //Start read of next packet
-  m_availableSphre.release(); //Force exiting the waiting state
-}
-
-//0 for non-blocking (returns immediately), -1 for infinite blocking
-/*virtual*/ int USBSerialStream::write(uint8_t* buf, size_t length, uint32_t timeout/*=-1*/)
-{
-  DBG("Trying to write %d chars", length);
-  do
-  {
-    int ret = waitSpace(timeout);
-    if(ret)
-    {
-      WARN("Error %d while waiting for space");
-      return ret;
-    }
-    int writeLen = MIN( space(), length );
-    DBG("Writing %d chars", length);
-    setupWriteableISR(false);
-    while(writeLen)
-    {
-      m_outBuf.queue(*buf);
-      buf++;
-      length--;
-      writeLen--;
-    }
-    setupWriteableISR(true);
-  } while(length);
-  //If m_serial tx fifo is empty we need to start the packet write
-  setupWriteableISR(false);
-  if( m_outBuf.available() && m_serialTxFifoEmpty )
-  {
-    writeable();
-  }
-  setupWriteableISR(true);
-  DBG("Write successful");
-  return OK;
-}
-
-/*virtual*/ size_t USBSerialStream::space()
-{
-  setupWriteableISR(false); //m_outBuf.available() is not reentrant
-  size_t len = CIRCBUF_SIZE - m_outBuf.available();
-  setupWriteableISR(true);
-  return len;
-}
-
-/*virtual*/ int USBSerialStream::waitSpace(uint32_t timeout/*=-1*/) //Wait for space to be available
-{
-  int ret;
-  if(space()) //Is still space already left?
-  {
-    m_spaceSphre.wait(0); //Clear the queue as space is available
-    return OK;
-  }
-
-  DBG("Waiting for data space %d ms (-1 is infinite)", timeout);
-  ret = m_spaceSphre.wait(timeout); //Wait for space to be made or for abort
-  if(ret <= 0)
-  {
-    DBG("Timeout");
-    return NET_TIMEOUT;
-  }
-  if(!space()) //Even if abort has been called, return that space is available
-  {
-    DBG("Aborted");
-    return NET_INTERRUPTED;
-  }
-  m_spaceSphre.wait(0); //Clear the queue as space is available
-  return OK;
-}
-
-/*virtual*/ int USBSerialStream::abortWrite() //Abort current writing (or waiting) operation
-{
-  if( !space() ) //If there is space left, no need to abort
-  {
-    m_spaceSphre.release(); //Force exiting the waiting state
-  }
-  return OK;
-}
-
-void USBSerialStream::setupWriteableISR(bool en)
-{
-  m_serial.setupIrq(en, IUSBHostSerial::TxIrq);
-}
-
-void USBSerialStream::writeable() //Callback from m_serial when new space is available
-{
-  if(m_outBuf.isEmpty())
-  {
-    m_serialTxFifoEmpty = true;
-  }
-  else
-  {
-    m_serialTxFifoEmpty = false;
-    while(m_serial.writeable() && !m_outBuf.isEmpty())
-    {
-      uint8_t c;
-      m_outBuf.dequeue(&c);
-      m_serial.putc((char)c);
-    }
-    static volatile int i=0;
-    m_serial.writePacket(); //Start packet write
-  }
-  m_spaceSphre.release(); //Force exiting the waiting state
-}
--- a/main/drv/serial/usb/USBSerialStream.h	Fri Jun 08 13:30:06 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/* USBSerialStream.h */
-/*
-Copyright (C) 2011 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.
-*/
-
-#ifndef USBSERIALSTREAM_H_
-#define USBSERIALSTREAM_H_
-
-
-#include "core/fwk.h"
-
-#include "USB3GModule/IUSBHostSerial.h"
-#include "USB3GModule/IUSBHostSerialListener.h"
-
-#include "rtos.h"
-#include "core/MtxCircBuffer.h"
-
-/* Input Serial Stream for USB virtual serial ports interfaces
-This class is not thread-safe, except for the *Abort() methods that can be called by any thread/ISR
-*/
-#define CIRCBUF_SIZE 255
-class USBSerialStream : public IOStream, IUSBHostSerialListener
-{
-public:
-  USBSerialStream(IUSBHostSerial& serial);
-  /*virtual*/ ~USBSerialStream();
-
-  //0 for non-blocking (returns immediately), osWaitForever for infinite blocking
-  virtual int read(uint8_t* buf, size_t* pLength, size_t maxLength, uint32_t timeout=osWaitForever);
-  virtual size_t available();
-  virtual int waitAvailable(uint32_t timeout=osWaitForever); //Wait for data to be available
-  virtual int abortRead(); //Abort current reading (or waiting) operation
-
-
-  //0 for non-blocking (returns immediately), osWaitForever for infinite blocking
-  virtual int write(uint8_t* buf, size_t length, uint32_t timeout=osWaitForever);
-  virtual size_t space();
-  virtual int waitSpace(uint32_t timeout=osWaitForever); //Wait for space to be available
-  virtual int abortWrite(); //Abort current writing (or waiting) operation
-
-private:
-  IUSBHostSerial& m_serial;
-  volatile bool m_serialTxFifoEmpty;
-
-  void setupReadableISR(bool en);
-  virtual void readable(); //Callback from m_serial when new data is available
-
-  Semaphore m_availableSphre; //Used for signalling
-
-  void setupWriteableISR(bool en);
-  virtual void writeable(); //Callback from m_serial when new space is available
-
-  Semaphore m_spaceSphre; //Used for signalling
-
-  MtxCircBuffer<uint8_t, CIRCBUF_SIZE + 1> m_inBuf;
-  MtxCircBuffer<uint8_t, CIRCBUF_SIZE + 1> m_outBuf;
-};
-
-#endif /* USBSERIALSTREAM_H_ */
--- a/main/if/ip/PPPIPInterface.cpp	Fri Jun 08 13:30:06 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,262 +0,0 @@
-/* PPPIPInterface.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 //Maximum verbosity
-#ifndef __MODULE__
-#define __MODULE__ "PPPIPInterface.cpp"
-#endif
-
-#include "core/fwk.h"
-#include "rtos.h"
-
-#include "PPPIPInterface.h"
-
-extern "C" {
-#include "lwip/ip_addr.h"
-#include "lwip/inet.h"
-#include "netif/ppp/ppp.h"
-}
-
-#if NET_PPP
-
-PPPIPInterface::PPPIPInterface(IOStream* pStream) : LwIPInterface(), m_linkStatusSphre(1), m_pppErrCode(0), m_pStream(pStream), m_streamAvail(true), m_pppd(-1)
-{
-  m_linkStatusSphre.wait();
-}
-
-/*virtual*/ PPPIPInterface::~PPPIPInterface()
-{
-
-}
-
-/*virtual*/ int PPPIPInterface::init() //Init PPP-specific stuff, create the right bindings, etc
-{
-  DBG("Initializing LwIP");
-  LwIPInterface::init(); //Init LwIP, NOT including PPP
-  DBG("Initializing PPP");
-  pppInit();
-  DBG("Done");
-  return OK;
-}
-
-int PPPIPInterface::setup(const char* user, const char* pw)
-{
-  DBG("Configuring PPP authentication method");
-  pppSetAuth(PPPAUTHTYPE_ANY, user, pw);
-  DBG("Done");
-  return OK;
-}
-
-/*virtual*/ int PPPIPInterface::connect()
-{
-  DBG("Trying to connect with PPP");
-  m_linkStatusSphre.wait(0);
-  if((m_pppd != -1) && (m_pppErrCode == 0)) //Already connected
-  {
-    return NET_INVALID;
-  }
-  int ret = pppOverSerialOpen(this, PPPIPInterface::linkStatusCb, this);
-  if(ret < 0)
-  {
-    switch(ret)
-    {
-    case PPPERR_OPEN:
-    default:
-      return NET_FULL; //All available resources are already used
-    }
-  }
-  m_pppd = ret; //PPP descriptor
-  m_linkStatusSphre.wait(); //Block indefinitely; there should be a timeout there
-  if(m_pppErrCode != PPPERR_NONE)
-  {
-    m_pppd = -1;
-  }
-  switch(m_pppErrCode)
-  {
-  case PPPERR_NONE: //Connected OK
-    return OK;
-  case PPPERR_CONNECT: //Connection lost
-    return NET_INTERRUPTED;
-  case PPPERR_AUTHFAIL: //Authentication failed
-    return NET_AUTH;
-  case PPPERR_PROTOCOL: //Protocol error
-    return NET_PROTOCOL;
-  default:
-    return NET_UNKNOWN;
-  }
-}
-
-/*virtual*/ int PPPIPInterface::disconnect()
-{
-  int ret = m_linkStatusSphre.wait(0);
-  if(ret > 0) //Already disconnected?
-  {
-    m_pppd = -1; //Discard PPP descriptor
-    switch(m_pppErrCode)
-      {
-      case PPPERR_CONNECT: //Connection terminated
-      case PPPERR_AUTHFAIL: //Authentication failed
-      case PPPERR_PROTOCOL: //Protocol error
-      case PPPERR_USER:
-        return OK;
-      default:
-        return NET_UNKNOWN;
-      }
-  }
-  else
-  {
-    if(m_pppd == -1)
-    {
-      return NET_INVALID;
-    }
-    pppClose(m_pppd);
-    do
-    {
-      m_linkStatusSphre.wait(); //Block indefinitely; there should be a timeout there
-      DBG("Received PPP err code %d", m_pppErrCode);
-    } while(m_pppErrCode != PPPERR_USER);
-    m_pppd = -1; //Discard PPP descriptor
-  }
-  return OK;
-}
-
-/*static*/ void PPPIPInterface::linkStatusCb(void *ctx, int errCode, void *arg) //PPP link status
-{
-  PPPIPInterface* pIf = (PPPIPInterface*)ctx;
-  struct ppp_addrs* addrs = (struct ppp_addrs*) arg;
-
-  switch(errCode)
-  {
-  case PPPERR_NONE:
-    WARN("Connected via PPP.");
-    DBG("Local IP address: %s", inet_ntoa(addrs->our_ipaddr));
-    DBG("Netmask: %s", inet_ntoa(addrs->netmask));
-    DBG("Remote IP address: %s", inet_ntoa(addrs->his_ipaddr));
-    DBG("Primary DNS: %s", inet_ntoa(addrs->dns1));
-    DBG("Secondary DNS: %s", inet_ntoa(addrs->dns2));
-    break;
-  case PPPERR_CONNECT: //Connection lost
-    WARN("Connection lost/terminated");
-    break;
-  case PPPERR_AUTHFAIL: //Authentication failed
-    WARN("Authentication failed");
-    break;
-  case PPPERR_PROTOCOL: //Protocol error
-    WARN("Protocol error");
-    break;
-  case PPPERR_USER:
-    WARN("Disconnected by user");
-    break;
-  default:
-    WARN("Unknown error (%d)", errCode);
-    break;
-  }
-
-  pIf->m_linkStatusSphre.wait(0); //If previous event has not been handled, "delete" it now
-  pIf->m_pppErrCode = errCode;
-  pIf->m_linkStatusSphre.release();
-}
-
-//LwIP PPP implementation
-extern "C"
-{
-
-/**
- * Writes to the serial device.
- *
- * @param fd serial device handle
- * @param data pointer to data to send
- * @param len length (in bytes) of data to send
- * @return number of bytes actually sent
- *
- * @note This function will block until all data can be sent.
- */
-u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len)
-{
-  DBG("sio_write");
-  PPPIPInterface* pIf = (PPPIPInterface*)fd;
-  int ret;
-  if(!pIf->m_streamAvail) //If stream is not available (it is a shared resource) don't go further
-  {
-    return 0;
-  }
-  ret = pIf->m_pStream->write(data, len, osWaitForever); //Blocks until all data is sent or an error happens
-  if(ret != OK)
-  {
-    return 0;
-  }
-  return len;
-}
-
-/**
- * Reads from the serial device.
- *
- * @param fd serial device handle
- * @param data pointer to data buffer for receiving
- * @param len maximum length (in bytes) of data to receive
- * @return number of bytes actually received - may be 0 if aborted by sio_read_abort
- *
- * @note This function will block until data can be received. The blocking
- * can be cancelled by calling sio_read_abort().
- */
-u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len)
-{
-  DBG("sio_read");
-  PPPIPInterface* pIf = (PPPIPInterface*)fd;
-  int ret;
-  size_t readLen;
-  if(!pIf->m_streamAvail) //If stream is not available (it is a shared resource) don't go further
-  {
-    WARN("EXIT NOT AVAIL");
-    return 0;
-  }
-  ret = pIf->m_pStream->read(data, &readLen, len, osWaitForever); //Blocks until some data is received or an error happens
-  if(ret != OK)
-  {
-    return 0;
-  }
-  DBG("ret");
-  return readLen;
-}
-
-/**
- * Aborts a blocking sio_read() call.
- *
- * @param fd serial device handle
- */
-void sio_read_abort(sio_fd_t fd)
-{
-  DBG("sio_read_abort");
-  PPPIPInterface* pIf = (PPPIPInterface*)fd;
-  if(!pIf->m_streamAvail) //If stream is not available (it is a shared resource) don't go further
-  {
-    return;
-  }
-  pIf->m_pStream->abortRead();
-  DBG("ret");
-}
-
-}
-
-#endif
-
--- a/main/if/ip/PPPIPInterface.h	Fri Jun 08 13:30:06 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/* PPPIPInterface.h */
-/*
-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.
-*/
-
-#ifndef PPPIPINTERFACE_H_
-#define PPPIPINTERFACE_H_
-
-#include "core/fwk.h"
-
-#include "LwIPInterface.h"
-
-#include "lwip/sio.h"
-
-namespace rtos {
-class Semaphore;
-}
-using namespace rtos;
-
-/** Interface using PPP to connect to an IP-based network
- *
- */
-class PPPIPInterface : public LwIPInterface
-{
-public:
-	PPPIPInterface(IOStream* pStream);
-	virtual ~PPPIPInterface();
-
-	virtual int init(); //Init PPP-specific stuff, create the right bindings, etc
-	int setup(const char* user, const char* pw); //Setup authentication
-  virtual int connect();
-  virtual int disconnect();
-
-private:
-	static void linkStatusCb(void *ctx, int errCode, void *arg); //PPP link status
-	Semaphore m_linkStatusSphre;
-	int m_pppErrCode;
-
-	IOStream* m_pStream; //Serial stream
-	bool m_streamAvail;
-
-	int m_pppd;
-
-	friend u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len);
-	friend u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len);
-	friend void sio_read_abort(sio_fd_t fd);
-};
-
-#endif /* PPPIPINTERFACE_H_ */
--- a/main/if/sms/SMSInterface.cpp	Fri Jun 08 13:30:06 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,390 +0,0 @@
-/* SMSInterface.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__ 4
-#ifndef __MODULE__
-#define __MODULE__ "SMSInterface.cpp"
-#endif
-
-#include "core/fwk.h"
-
-#include "SMSInterface.h"
-
-#include <cstdio>
-
-#define DEFAULT_TIMEOUT 10000
-
-SMSInterface::SMSInterface(ATCommandsInterface* pIf) : m_pIf(pIf), m_msg(NULL), m_maxMsgLength(0), m_msisdn(NULL), /*m_msgCount(0),*/
-m_msgRefListCount(0), m_needsUpdate(true), m_state(SMS_IDLE)
-{
-  m_pIf->registerEventsHandler(this); //Add us to the unsolicited result codes handlers
-}
-
-int SMSInterface::init()
-{
-  DBG("Set format");
-  //Set Text mode format
-  int ret = m_pIf->executeSimple("AT+CMGF=1", NULL, DEFAULT_TIMEOUT);
-  if(ret != OK)
-  {
-    return NET_PROTOCOL;
-  }
-
-  DBG("Setup new messages indication");
-  //Setup new messages indication
-  ret = m_pIf->executeSimple("AT+CNMI=2,1,0,0,0", NULL, DEFAULT_TIMEOUT);
-  if(ret != OK)
-  {
-    return NET_PROTOCOL;
-  }
-
-  DBG("Try to fetch inbox");
-  m_inboxMtx.lock();
-  if( m_needsUpdate )
-  {
-    ret = updateInbox(); //Fetch existing messages references
-    if(ret)
-    {
-      m_inboxMtx.unlock();
-      return NET_PROTOCOL;
-    }
-  }
-  m_inboxMtx.unlock();
-
-  DBG("Initialization done");
-  return OK;
-}
-
-int SMSInterface::send(const char* number, const char* message)
-{
-  if( strlen(number) > 16 )
-  {
-    return NET_INVALID; //Number too long to match 3GPP spec
-  }
-
-  int ret;
-
-  //Prepare infos
-  m_state = SMS_SEND_CMD_SENT;
-  m_msg = (char*) message;
-
-  DBG("Send SM");
-  //Send command
-  char cmd[32];
-  std::sprintf(cmd, "AT+CMGS=\"%s\"", number);
-  ret = m_pIf->execute(cmd, this, NULL, DEFAULT_TIMEOUT);
-
-  if( (ret != OK) || (m_state != SMS_CMD_PROCESSED) )
-  {
-    WARN("ret %d, state %d", ret, m_state);
-    m_state = SMS_IDLE;
-    return NET_PROTOCOL;
-  }
-
-  DBG("SM sent");
-  m_state = SMS_IDLE;
-  return OK;
-}
-
-
-int SMSInterface::get(char* number, char* message, size_t maxLength)
-{
-  if( maxLength < 1  )
-  {
-    return NET_INVALID; //Buffer too short
-  }
-
-  int ret;
-
-  DBG("Get next message");
-  m_inboxMtx.lock();
-  if(m_msgRefListCount == 0 && m_needsUpdate)
-  {
-    ret = updateInbox();
-    if (ret)
-    {
-      m_inboxMtx.unlock();
-      return ret;
-    }
-  }
-
-  if(m_msgRefListCount == 0)
-  {
-    m_inboxMtx.unlock();
-    return NET_EMPTY; //No message to read
-  }
-
-  //Prepare infos
-  m_state = SMS_GET_CMD_SENT;
-  m_msisdn = (char*) number;
-  m_msg = (char*) message;
-  m_maxMsgLength = maxLength;
-
-  DBG("Get SMS");
-  //List command
-  char cmd[32];
-  std::sprintf(cmd, "AT+CMGR=%d", m_msgRefList[0]);
-  ret = m_pIf->execute(cmd, this, NULL, DEFAULT_TIMEOUT);
-  if( ret != OK )
-  {
-    WARN("AT+CMGR returned %d", ret);
-    m_state = SMS_IDLE;
-    m_inboxMtx.unlock();
-    return NET_PROTOCOL;
-  }
-
-  if (m_state != SMS_CMD_PROCESSED)
-  {
-    m_state = SMS_IDLE;
-    m_inboxMtx.unlock();
-    return NET_EMPTY;
-  }
-
-  m_state = SMS_IDLE;
-
-  DBG("Deleting message");
-  //Delete message from outbox
-  std::sprintf(cmd, "AT+CMGD=%d", m_msgRefList[0]);
-  ret = m_pIf->executeSimple(cmd, NULL, DEFAULT_TIMEOUT);
-  if(ret != OK)
-  {
-    m_inboxMtx.unlock();
-    WARN("Could not delete message");
-  }
-
-  //Remove message from list
-  std::memmove(m_msgRefList, m_msgRefList+1, m_msgRefListCount-1);
-  m_msgRefListCount--;
-
-  m_inboxMtx.unlock();
-
-  return OK;
-}
-
-
-int SMSInterface::getCount(size_t* pCount)
-{
-  int ret;
-
-  m_inboxMtx.lock();
-  if( m_needsUpdate )
-  {
-    ret = updateInbox();
-    if(ret)
-    {
-      m_inboxMtx.unlock();
-      return NET_PROTOCOL;
-    }
-  }
-
-  *pCount = m_msgRefListCount;
-  m_inboxMtx.unlock();
-
-  return OK;
-}
-
-
-/*virtual*/ int SMSInterface::onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
-{
-  if(m_state == SMS_SEND_CMD_SENT)
-  {
-    if( std::sscanf(line, "+CMGS: %*d") == 0 )
-    {
-      DBG("SM sent");
-      m_state = SMS_CMD_PROCESSED;
-    }
-  }
-  else if(m_state == SMS_GET_CMD_SENT)
-  {
-    DBG("Header: %s", line);
-    if( std::sscanf(line, "+CMGR: %*[^,],\"%16[^\"]\"", m_msisdn) == 1 ) //Get message ref
-    {
-      m_state = SMS_GET_HDR_RECEIVED;
-    }
-  }
-  else if(m_state == SMS_GET_HDR_RECEIVED)
-  {
-    DBG("Message: %s", line);
-    size_t cpyLen = MIN( std::strlen(line), m_maxMsgLength - 1 );
-    std::memcpy( m_msg, line, cpyLen );
-    m_msg[cpyLen] = '\0';
-    m_state = SMS_CMD_PROCESSED;
-  }
-  else if(m_state == SMS_GET_COUNT_CMD_SENT)
-  {
-    DBG("Header: %s", line);
-    int msgRef;
-    if( std::sscanf(line, "+CMGL: %d", &msgRef) == 1 )
-    {
-      m_state = SMS_GET_COUNT_HDR_RECEIVED;
-      //Add message to list
-      if(m_msgRefListCount < MAX_SM)
-      {
-        m_msgRefList[m_msgRefListCount] = msgRef;
-      }
-      m_msgRefListCount++; //Always count message
-      DBG("m_msgRefListCount=%d",m_msgRefListCount);
-    }
-  }
-  else if(m_state == SMS_GET_COUNT_HDR_RECEIVED)
-  {
-    DBG("Message (debug only): %s", line); //For debug only
-    m_state = SMS_GET_COUNT_CMD_SENT;
-  }
-  return OK;
-}
-
-/*virtual*/ int SMSInterface::onNewEntryPrompt(ATCommandsInterface* pInst)
-{
-  if(m_state == SMS_SEND_CMD_SENT)
-  {
-    char* crPtr = strchr(m_msg, CR);
-    if(crPtr != NULL)
-    {
-      int crPos = crPtr - m_msg;
-      //Replace m_inputBuf[crPos] with null-terminating char
-      m_msg[crPos] = '\x0';
-
-      //If there is a CR char, split message there
-
-      //Do print the message
-      int ret = pInst->sendData(m_msg);
-      if(ret)
-      {
-        return ret;
-      }
-
-      char cr[2] = {CR, '\0'};
-      ret = pInst->sendData(cr);
-      if(ret)
-      {
-        return ret;
-      }
-
-      m_msg += crPos;
-
-      if(m_msg[0] == LF)
-      {
-        m_msg++; //Discard LF char as well
-      }
-
-      return NET_MOREINFO;
-    }
-    else
-    {
-      //Do print the message
-      pInst->sendData(m_msg);
-      return OK;
-    }
-  }
-
-  return OK;
-}
-
-/*virtual*/ bool SMSInterface::isATCodeHandled(const char* atCode) //Is this AT code handled
-{
-  DBG("AT code is %s", atCode);
-  if( strcmp("+CMTI", atCode) == 0 )
-  {
-    return true;
-  }
-
-  DBG("Not handled");
-  return false;
-}
-
-/*virtual*/ void SMSInterface::onDispatchStart()
-{
-
-
-}
-
-/*virtual*/ void SMSInterface::onDispatchStop()
-{
-
-}
-
-/*virtual*/ void SMSInterface::onEvent(const char* atCode, const char* evt)
-{
-  if( strcmp("+CMTI", atCode) != 0 )
-  {
-    return; //Not supported
-  }
-
-  DBG("Unsollicited result code: %s - %s", atCode, evt);
-
-  //Get index
-  int msgRef;
-  if( std::sscanf(evt, "\"SM\",%d", &msgRef) == 1 )
-  {
-    DBG("Adding message to list (ref %d)", msgRef);
-    m_inboxMtx.lock();
-    //Add message to list
-    if(m_msgRefListCount < MAX_SM)
-    {
-      m_msgRefList[m_msgRefListCount] = msgRef;
-    }
-    else
-    {
-      m_needsUpdate = true;
-    }
-    m_msgRefListCount++; //Always count message
-    m_inboxMtx.unlock();
-  }
-}
-
-int SMSInterface::updateInbox()
-{
-  //Get memory indexes of unread messages
-  m_state = SMS_GET_COUNT_CMD_SENT;
-
-  DBG("Updating inbox");
-  m_msgRefListCount = 0; //Reset list
-
-  int ret = m_pIf->execute("AT+CMGL=\"REC UNREAD\"", this, NULL, DEFAULT_TIMEOUT);
-  if( ret != OK )
-  {
-    WARN("AT+CMGL returned %d", ret);
-    m_state = SMS_IDLE;
-    m_msgRefListCount = 0; //List could be invalid
-    m_needsUpdate = true;
-    return NET_PROTOCOL;
-  }
-
-  DBG("%d incoming messages in inbox", m_msgRefListCount);
-
-  if( m_msgRefListCount > MAX_SM )
-  {
-    m_needsUpdate = true;
-  }
-  else
-  {
-    m_needsUpdate = false;
-  }
-
-  m_state = SMS_IDLE;
-
-  return OK;
-}
-
-
--- a/main/if/sms/SMSInterface.h	Fri Jun 08 13:30:06 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-/* SMSInterface.h */
-/*
-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.
-*/
-
-#ifndef SMSINTERFACE_H_
-#define SMSINTERFACE_H_
-
-#include "core/fwk.h"
-
-#include "rtos.h"
-
-#include "drv/at/ATCommandsInterface.h"
-
-#define MAX_SM 8
-
-/** Component to use the Short Messages Service (SMS)
- *
- */
-class SMSInterface : protected IATCommandsProcessor, IATEventsHandler
-{
-public:
-  /** Create SMSInterface instance
-     @param pIf Pointer to the ATCommandsInterface instance to use
-   */
-  SMSInterface(ATCommandsInterface* pIf);
-
-  /** Initialize interface
-    Configure SMS commands & register for SMS-related unsolicited result codes
-   */
-  int init();
-
-  /** Send a SM
-     @param number The receiver's phone number
-     @param message The message to send
-     @return 0 on success, error code on failure
-   */
-  int send(const char* number, const char* message);
-
-
-  /** Receive a SM
-     @param number Pointer to a buffer to store the sender's phone number (must be at least 17 characters-long, including the space for the null-terminating char)
-     @param message Pointer to a buffer to store the the incoming message
-     @param maxLength Maximum message length that can be stored in buffer (including null-terminating character)
-     @return 0 on success, error code on failure
-   */
-  int get(char* number, char* message, size_t maxLength);
-
-
-  /** Get the number of SMs in the incoming box
-     @param pCount pointer to store the number of unprocessed SMs on
-     @return 0 on success, error code on failure
-   */
-  int getCount(size_t* pCount);
-
-protected:
-  //IATCommandsProcessor
-  virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line);
-  virtual int onNewEntryPrompt(ATCommandsInterface* pInst);
-
-  //IATEventsHandler
-  virtual bool isATCodeHandled(const char* atCode); //Is this AT code handled
-  virtual void onDispatchStart();
-  virtual void onDispatchStop();
-  virtual void onEvent(const char* atCode, const char* evt);
-
-  //Updates messages count/references
-  int updateInbox();
-
-private:
-  ATCommandsInterface* m_pIf;
-
-  //Current message
-  char* m_msg;
-  size_t m_maxMsgLength;
-  char* m_msisdn;
-
-  //Messages list
-  int m_msgRefList[MAX_SM];
-  size_t m_msgRefListCount;
-  bool m_needsUpdate;
-  Mutex m_inboxMtx; //To protect concurrent accesses btw the user's thread and the AT thread
-
-  enum { SMS_IDLE, SMS_SEND_CMD_SENT, SMS_GET_CMD_SENT, SMS_GET_HDR_RECEIVED, SMS_GET_COUNT_CMD_SENT, SMS_GET_COUNT_HDR_RECEIVED, SMS_CMD_PROCESSED } m_state;
-};
-
-#endif /* SMSINTERFACE_H_ */
--- a/main/if/ussd/USSDInterface.cpp	Fri Jun 08 13:30:06 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,152 +0,0 @@
-/* USSDInterface.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__ 4
-#ifndef __MODULE__
-#define __MODULE__ "USSDInterface.cpp"
-#endif
-
-#include "core/fwk.h"
-
-#include "USSDInterface.h"
-
-#include <cstdio>
-
-#define DEFAULT_TIMEOUT 10000
-#define USSD_TIMEOUT 15000
-
-USSDInterface::USSDInterface(ATCommandsInterface* pIf) : m_pIf(pIf), m_responseMtx(), m_responseSphre(1), m_result(NULL), m_maxResultLength(0)
-{
-  m_responseSphre.wait(0); //Take ownership of the semaphore
-  m_pIf->registerEventsHandler(this); //Add us to the unsolicited result codes handlers
-}
-
-int USSDInterface::init()
-{
-  DBG("Initialization done");
-  return OK;
-}
-
-int USSDInterface::send(const char* command, char* result, size_t maxLength)
-{
-  if (strlen(command) > 20) //Prevent buffer overflow
-  {
-    return NET_TOOSMALL;
-  }
-
-  m_responseMtx.lock();
-  m_result = result;
-  m_maxResultLength = maxLength;
-  m_responseMtx.unlock();
-
-  m_responseSphre.wait(0); //Make sure there is not a pending result that needs to be discarded
-
-  DBG("Send USSD command & register for unsolicited result codes");
-  //Send USSD command to the network
-  char cmd[32];
-  std::sprintf(cmd, "AT+CUSD=1,\"%s\"", command);
-  int ret = m_pIf->executeSimple(cmd, NULL, DEFAULT_TIMEOUT);
-  if( ret != OK )
-  {
-    return NET_PROTOCOL;
-  }
-
-  //Now wait for response
-  int res = m_responseSphre.wait(USSD_TIMEOUT);
-
-  //Reset data
-  m_responseMtx.lock();
-  m_result = NULL;
-  m_maxResultLength = 0;
-  m_responseMtx.unlock();
-
-  if(res <= 0)
-  {
-    DBG("No result received");
-    ret = m_pIf->executeSimple("AT+CUSD=2", NULL, DEFAULT_TIMEOUT); //Cancel command
-    if( ret != OK )
-    {
-      return NET_PROTOCOL;
-    }
-    return NET_TIMEOUT;
-  }
-
-  DBG("Result received: %s", result);
-
-  return OK;
-
-}
-
-/*virtual*/ bool USSDInterface::isATCodeHandled(const char* atCode) //Is this AT code handled
-{
-  DBG("AT code is %s", atCode);
-  if( strcmp("+CUSD", atCode) == 0 )
-  {
-    return true;
-  }
-
-  DBG("Not handled");
-  return false;
-}
-
-/*virtual*/ void USSDInterface::onDispatchStart()
-{
-
-
-}
-
-/*virtual*/ void USSDInterface::onDispatchStop()
-{
-
-}
-
-/*virtual*/ void USSDInterface::onEvent(const char* atCode, const char* evt)
-{
-  if( strcmp("+CUSD", atCode) != 0 )
-  {
-    return; //Not supported
-  }
-
-  char* pStart = (char*) strchr(evt,'\"');
-  if(pStart==NULL)
-  {
-    return; //Invalid/incomplete response
-  }
-  pStart++; //Point to first char of response
-  char* pEnd = (char*) strchr(pStart,'\"');
-  if(pEnd==NULL)
-  {
-    return; //Invalid/incomplete response
-  }
-  m_responseMtx.lock();
-  if(m_maxResultLength == 0) //No pending command
-  {
-    m_responseMtx.unlock();
-    return;
-  }
-  size_t cpyLen = MIN( pEnd - pStart, m_maxResultLength - 1 );
-  memcpy(m_result, pStart, cpyLen);
-  m_result[cpyLen] = '\0';
-  m_responseMtx.unlock();
-  m_responseSphre.release(); //Signal user thread that response is ready
-}
--- a/main/if/ussd/USSDInterface.h	Fri Jun 08 13:30:06 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/* USSDInterface.h */
-/*
-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.
-*/
-
-#ifndef USSDINTERFACE_H_
-#define USSDINTERFACE_H_
-
-#include "core/fwk.h"
-
-#include "rtos.h"
-
-#include "drv/at/ATCommandsInterface.h"
-
-/** Component to send/receive Unstructured Supplementary Service Data (USSD)
- *
- */
-class USSDInterface : protected IATEventsHandler
-{
-public:
-  /** Create USSDInterface instance
-     @param pIf Pointer to the ATCommandsInterface instance to use
-   */
-  USSDInterface(ATCommandsInterface* pIf);
-
-  /** Initialize interface
-   Configure USSD commands & register for USSD-related unsolicited result codes
-  */
-  int init();
-
-  /** Send a USSD command & wait for its result
-    @param command The command to send
-    @param result Buffer in which to store the result
-    @param maxLength Maximum result length that can be stored in buffer (including null-terminating character)
-    @return 0 on success, error code on failure
-  */
-  int send(const char* command, char* result, size_t maxLength);
-
-protected:
-  //IATEventsHandler
-  virtual bool isATCodeHandled(const char* atCode); //Is this AT code handled
-  virtual void onDispatchStart();
-  virtual void onDispatchStop();
-  virtual void onEvent(const char* atCode, const char* evt);
-
-private:
-  ATCommandsInterface* m_pIf;
-  Mutex m_responseMtx; //To protect concurrent accesses btw the user's thread and the AT thread
-  Semaphore m_responseSphre;
-
-  //Result
-  char* m_result;
-  size_t m_maxResultLength;
-
-};
-
-
-#endif /* USSDINTERFACE_H_ */
--- a/main/lwipopts.h	Fri Jun 08 13:30:06 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/* lwipopts.h */
-/*
- 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.
- */
-
-#ifndef LWIPOPTS_H_
-#define LWIPOPTS_H_
- 
-#include "lwipopts_common.h" //Get common options
-
-///PPP Options
-
-#define TCP_SND_BUF                     (3 * 536)
-#define TCP_WND                         (2 * 536)
-
-#define LWIP_ARP 0
-
-#define PPP_SUPPORT 1
-#define CHAP_SUPPORT                    1
-#define PAP_SUPPORT                     1
-#define PPP_THREAD_STACKSIZE            4*192
-#define PPP_THREAD_PRIO 0
-
-#define MAXNAMELEN                      64     /* max length of hostname or name for auth */
-#define MAXSECRETLEN                    64
-
-#endif /* LWIPOPTS_H_ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/serial/io/IOSerialStream.cpp	Tue Jun 26 13:44:59 2012 +0000
@@ -0,0 +1,257 @@
+/* IOSerialStream.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__ 0 //Maximum verbosity
+#ifndef __MODULE__
+#define __MODULE__ "IOSerialStream.cpp"
+#endif
+
+#include "core/fwk.h"
+
+#include <stdio.h>
+
+#include "IOSerialStream.h"
+
+IOSerialStream::IOSerialStream(mbed::Serial& serial) : m_serial(serial), m_serialTxFifoEmpty(true),
+m_availableSphre(1), m_spaceSphre(1), m_inBuf(), m_outBuf()
+{
+  m_availableSphre.wait();
+  m_spaceSphre.wait();
+  //Attach interrupts
+  m_serial.attach(this, &IOSerialStream::readable, mbed::Serial::RxIrq);
+  m_serial.attach(this, &IOSerialStream::writeable, mbed::Serial::TxIrq);
+}
+
+/*virtual*/ IOSerialStream::~IOSerialStream()
+{
+  m_serial.attach(NULL, mbed::Serial::RxIrq);
+  m_serial.attach(NULL, mbed::Serial::TxIrq);
+}
+
+//0 for non-blocking (returns immediately), osWaitForever for infinite blocking
+/*virtual*/ int IOSerialStream::read(uint8_t* buf, size_t* pLength, size_t maxLength, uint32_t timeout/*=osWaitForever*/)
+{
+  DBG("Trying to read at most %d chars", maxLength);
+  int ret = waitAvailable(timeout);
+  if(ret)
+  {
+    WARN("Error %d while waiting for incoming data");
+    return ret;
+  }
+  int readLen = MIN( available(), maxLength );
+  *pLength = readLen;
+  setupReadableISR(false);
+  while(readLen--)
+  {
+    m_inBuf.dequeue(buf);
+    buf++;
+  }
+  setupReadableISR(true);
+  DBG("Read %d chars successfully", *pLength);
+  return OK;
+}
+
+/*virtual*/ size_t IOSerialStream::available()
+{
+  setupReadableISR(false); //m_inBuf.available() is not reentrant
+  size_t len = m_inBuf.available();
+  setupReadableISR(true);
+  return len;
+}
+
+/*virtual*/ int IOSerialStream::waitAvailable(uint32_t timeout/*=osWaitForever*/) //Wait for data to be available
+{
+  int ret;
+  if(available()) //Is data already available?
+  {
+    m_availableSphre.wait(0); //Clear the queue as data is available
+    return OK;
+  }
+
+  DBG("Waiting for data availability %d ms (-1 is infinite)", timeout);
+  ret = m_availableSphre.wait(timeout); //Wait for data to arrive or for abort
+  if(ret <= 0)
+  {
+    DBG("Timeout");
+    return NET_TIMEOUT;
+  }
+  if(!available()) //Even if abort has been called, return that data is available
+  {
+    DBG("Aborted");
+    return NET_INTERRUPTED;
+  }
+  DBG("Finished waiting");
+  m_availableSphre.wait(0); //Clear the queue as data is available
+  return OK;
+}
+
+/*virtual*/ int IOSerialStream::abortRead() //Abort current reading (or waiting) operation
+{
+  if( !available() ) //If there is data pending, no need to abort
+  {
+    m_availableSphre.release(); //Force exiting the waiting state; kludge to pass a RC directly
+  }
+  else
+  {
+    DBG("Serial is readable"); ;
+  }
+  return OK;
+}
+
+void IOSerialStream::setupReadableISR(bool en)
+{
+  if(en)
+  {
+    ((LPC_UART_TypeDef *)(UART_3))->IER |= 1 << 0;
+  }
+  else
+  {
+    ((LPC_UART_TypeDef *)(UART_3))->IER &= ~(1 << 0);
+  }
+}
+
+void IOSerialStream::readable() //Callback from m_serial when new data is available
+{
+  do
+  {
+    m_inBuf.queue(((LPC_UART_TypeDef *)UART_3)->RBR); //FIXME mbed libraries this is an awful kludge
+  } while(m_serial.readable());
+  m_availableSphre.release(); //Force exiting the waiting state
+}
+
+//0 for non-blocking (returns immediately), osWaitForever for infinite blocking
+/*virtual*/ int IOSerialStream::write(uint8_t* buf, size_t length, uint32_t timeout/*=osWaitForever*/)
+{
+  DBG("Trying to write %d chars", length);
+  int ret = waitSpace(timeout);
+  if(ret)
+  {
+    WARN("Error %d while waiting for space");
+    return ret;
+  }
+  DBG("Writing %d chars", length);
+  setupWriteableISR(false);
+  while(length)
+  {
+    m_outBuf.queue(*buf);
+    buf++;
+    length--;
+    if(length && !space())
+    {
+      DBG("Waiting to write remaining %d chars", length);
+      setupWriteableISR(true);
+      ret = waitSpace(timeout);
+      if(ret)
+      {
+        WARN("Error %d while waiting for space");
+        return ret;
+      }
+      setupWriteableISR(false);
+    }
+  }
+  //If m_serial tx fifo is empty we need to manually tx a byte in order to trigger the interrupt
+  if( m_outBuf.available() && m_serialTxFifoEmpty )
+  {
+    m_serialTxFifoEmpty = false;
+    uint8_t c;
+    m_outBuf.dequeue(&c);
+    //m_serial.putc((char)c);
+    ((LPC_UART_TypeDef *)UART_3)->THR = c; //FIXME awful kludge
+  }
+  setupWriteableISR(true);
+  DBG("Write successful");
+  return OK;
+}
+
+/*virtual*/ size_t IOSerialStream::space()
+{
+  setupWriteableISR(false); //m_outBuf.available() is not reentrant
+  size_t len = CIRCBUF_SIZE - m_outBuf.available();
+  setupWriteableISR(true);
+  return len;
+}
+
+/*virtual*/ int IOSerialStream::waitSpace(uint32_t timeout/*=osWaitForever*/) //Wait for space to be available
+{
+  int ret;
+  if(space()) //Is still space already left?
+  {
+    m_spaceSphre.wait(0); //Clear the queue as space is available
+    return OK;
+  }
+
+  DBG("Waiting for data space %d ms (-1 is infinite)", timeout);
+  ret = m_spaceSphre.wait(timeout); //Wait for space to be made or for abort
+  if(ret <= 0)
+  {
+    DBG("Timeout");
+    return NET_TIMEOUT;
+  }
+  if(!space()) //Even if abort has been called, return that space is available
+  {
+    DBG("Aborted");
+    return NET_INTERRUPTED;
+  }
+  m_spaceSphre.wait(0); //Clear the queue as space is available
+  return OK;
+}
+
+/*virtual*/ int IOSerialStream::abortWrite() //Abort current writing (or waiting) operation
+{
+  if( !space() ) //If there is space left, no need to abort
+  {
+    m_spaceSphre.release(); //Force exiting the waiting state
+  }
+  return OK;
+}
+
+void IOSerialStream::setupWriteableISR(bool en)
+{
+  if(en)
+  {
+    ((LPC_UART_TypeDef *)(UART_3))->IER |= 1 << 1;
+  }
+  else
+  {
+    ((LPC_UART_TypeDef *)(UART_3))->IER &= ~(1 << 1);
+  }
+}
+
+void IOSerialStream::writeable() //Callback from m_serial when new space is available
+{
+  if(m_outBuf.isEmpty())
+  {
+    m_serialTxFifoEmpty = true;
+  }
+  else
+  {
+    while(m_serial.writeable() && !m_outBuf.isEmpty())
+    {
+      uint8_t c;
+      m_outBuf.dequeue(&c);
+      //m_serial.putc((char)c);
+      ((LPC_UART_TypeDef *)UART_3)->THR = c; //FIXME awful kludge
+    }
+  }
+  m_spaceSphre.release(); //Force exiting the waiting state
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/serial/io/IOSerialStream.h	Tue Jun 26 13:44:59 2012 +0000
@@ -0,0 +1,77 @@
+/* IOSerialStream.h */
+/*
+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.
+*/
+
+#ifndef IOSERIALSTREAM_H_
+#define IOSERIALSTREAM_H_
+
+#include "core/fwk.h"
+
+#include "Serial.h"
+
+#include "rtos.h"
+#include "core/MtxCircBuffer.h"
+
+/** Input Serial Stream for physical serial interfaces (UART...)
+This class is not thread-safe, except for the *Abort() methods that can be called by any thread/ISR
+*/
+#define CIRCBUF_SIZE 255
+class IOSerialStream : public IOStream
+{
+public:
+  IOSerialStream(mbed::Serial& serial);
+  /*virtual*/ ~IOSerialStream();
+
+  //0 for non-blocking (returns immediately), osWaitForever for infinite blocking
+  virtual int read(uint8_t* buf, size_t* pLength, size_t maxLength, uint32_t timeout=osWaitForever);
+  virtual size_t available();
+  virtual int waitAvailable(uint32_t timeout=osWaitForever); //Wait for data to be available
+  virtual int abortRead(); //Abort current reading (or waiting) operation
+
+
+  //0 for non-blocking (returns immediately), osWaitForever for infinite blocking
+  virtual int write(uint8_t* buf, size_t length, uint32_t timeout=osWaitForever);
+  virtual size_t space();
+  virtual int waitSpace(uint32_t timeout=osWaitForever); //Wait for space to be available
+  virtual int abortWrite(); //Abort current writing (or waiting) operation
+
+private:
+
+  mbed::Serial& m_serial;
+  volatile bool m_serialTxFifoEmpty;
+
+  void setupReadableISR(bool en);
+  void readable(); //Callback from m_serial when new data is available
+
+  Semaphore m_availableSphre; //Used for signalling
+
+  void setupWriteableISR(bool en);
+  void writeable(); //Callback from m_serial when new space is available
+
+  Semaphore m_spaceSphre; //Used for signalling
+
+  MtxCircBuffer<uint8_t, CIRCBUF_SIZE + 1> m_inBuf;
+  MtxCircBuffer<uint8_t, CIRCBUF_SIZE + 1> m_outBuf;
+
+};
+
+#endif /* IOSERIALSTREAM_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/serial/usb/USBSerialStream.cpp	Tue Jun 26 13:44:59 2012 +0000
@@ -0,0 +1,237 @@
+/* USBSerialStream.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__ 0 //Maximum verbosity
+#ifndef __MODULE__
+#define __MODULE__ "USBSerialStream.cpp"
+#endif
+
+#include "core/fwk.h"
+
+#include <stdio.h>
+
+#include "USBSerialStream.h"
+
+
+USBSerialStream::USBSerialStream(IUSBHostSerial& serial) : m_serial(serial), m_serialTxFifoEmpty(true),
+m_availableSphre(1), m_spaceSphre(1), m_inBuf()
+{
+  m_availableSphre.wait();
+  m_spaceSphre.wait();
+  //Attach interrupts
+  m_serial.attach(this);
+}
+
+/*virtual*/ USBSerialStream::~USBSerialStream()
+{
+  m_serial.attach(NULL);
+}
+
+//0 for non-blocking (returns immediately), -1 for infinite blocking
+/*virtual*/ int USBSerialStream::read(uint8_t* buf, size_t* pLength, size_t maxLength, uint32_t timeout/*=osWaitForever*/)
+{
+  DBG("Trying to read at most %d chars", maxLength);
+  int ret = waitAvailable(timeout);
+  if(ret)
+  {
+    WARN("Error %d while waiting for incoming data", ret);
+    return ret;
+  }
+  int readLen = MIN( available(), maxLength );
+  *pLength = readLen;
+
+  setupReadableISR(false);
+  while(readLen--)
+  {
+    m_inBuf.dequeue(buf);
+    buf++;
+  }
+  setupReadableISR(true);
+  DBG("Read %d chars successfully", *pLength);
+  return OK;
+}
+
+/*virtual*/ size_t USBSerialStream::available()
+{
+  setupReadableISR(false); //m_inBuf.available() is not reentrant
+  size_t len = m_inBuf.available();
+  setupReadableISR(true);
+  return len;
+}
+
+/*virtual*/ int USBSerialStream::waitAvailable(uint32_t timeout/*=osWaitForever*/) //Wait for data to be available
+{
+  int ret;
+  if(available()) //Is data already available?
+  {
+    m_availableSphre.wait(0); //Clear the queue as data is available
+    return OK;
+  }
+
+  DBG("Waiting for data availability %d ms (-1 is infinite)", timeout);
+  ret = m_availableSphre.wait(timeout); //Wait for data to arrive or for abort
+  if(ret <= 0)
+  {
+    DBG("Timeout");
+    return NET_TIMEOUT;
+  }
+  if(!m_inBuf.available()) //Even if abort has been called, return that data is available
+  {
+    DBG("Aborted");
+    return NET_INTERRUPTED;
+  }
+  DBG("Finished waiting");
+  m_availableSphre.wait(0); //Clear the queue as data is available
+  return OK;
+}
+
+/*virtual*/ int USBSerialStream::abortRead() //Abort current reading (or waiting) operation
+{
+  if( /*!available()*/true ) //If there is data pending, no need to abort
+  {
+    m_availableSphre.release(); //Force exiting the waiting state
+  }
+  else
+  {
+    DBG("Serial is readable"); ;
+  }
+  return OK;
+}
+
+void USBSerialStream::setupReadableISR(bool en)
+{
+  m_serial.setupIrq(en, IUSBHostSerial::RxIrq);
+}
+
+void USBSerialStream::readable() //Callback from m_serial when new data is available
+{
+  while(m_serial.readable())
+  {
+    m_inBuf.queue(m_serial.getc());
+  }
+  m_serial.readPacket(); //Start read of next packet
+  m_availableSphre.release(); //Force exiting the waiting state
+}
+
+//0 for non-blocking (returns immediately), -1 for infinite blocking
+/*virtual*/ int USBSerialStream::write(uint8_t* buf, size_t length, uint32_t timeout/*=-1*/)
+{
+  DBG("Trying to write %d chars", length);
+  do
+  {
+    int ret = waitSpace(timeout);
+    if(ret)
+    {
+      WARN("Error %d while waiting for space");
+      return ret;
+    }
+    int writeLen = MIN( space(), length );
+    DBG("Writing %d chars", length);
+    setupWriteableISR(false);
+    while(writeLen)
+    {
+      m_outBuf.queue(*buf);
+      buf++;
+      length--;
+      writeLen--;
+    }
+    setupWriteableISR(true);
+  } while(length);
+  //If m_serial tx fifo is empty we need to start the packet write
+  setupWriteableISR(false);
+  if( m_outBuf.available() && m_serialTxFifoEmpty )
+  {
+    writeable();
+  }
+  setupWriteableISR(true);
+  DBG("Write successful");
+  return OK;
+}
+
+/*virtual*/ size_t USBSerialStream::space()
+{
+  setupWriteableISR(false); //m_outBuf.available() is not reentrant
+  size_t len = CIRCBUF_SIZE - m_outBuf.available();
+  setupWriteableISR(true);
+  return len;
+}
+
+/*virtual*/ int USBSerialStream::waitSpace(uint32_t timeout/*=-1*/) //Wait for space to be available
+{
+  int ret;
+  if(space()) //Is still space already left?
+  {
+    m_spaceSphre.wait(0); //Clear the queue as space is available
+    return OK;
+  }
+
+  DBG("Waiting for data space %d ms (-1 is infinite)", timeout);
+  ret = m_spaceSphre.wait(timeout); //Wait for space to be made or for abort
+  if(ret <= 0)
+  {
+    DBG("Timeout");
+    return NET_TIMEOUT;
+  }
+  if(!space()) //Even if abort has been called, return that space is available
+  {
+    DBG("Aborted");
+    return NET_INTERRUPTED;
+  }
+  m_spaceSphre.wait(0); //Clear the queue as space is available
+  return OK;
+}
+
+/*virtual*/ int USBSerialStream::abortWrite() //Abort current writing (or waiting) operation
+{
+  if( !space() ) //If there is space left, no need to abort
+  {
+    m_spaceSphre.release(); //Force exiting the waiting state
+  }
+  return OK;
+}
+
+void USBSerialStream::setupWriteableISR(bool en)
+{
+  m_serial.setupIrq(en, IUSBHostSerial::TxIrq);
+}
+
+void USBSerialStream::writeable() //Callback from m_serial when new space is available
+{
+  if(m_outBuf.isEmpty())
+  {
+    m_serialTxFifoEmpty = true;
+  }
+  else
+  {
+    m_serialTxFifoEmpty = false;
+    while(m_serial.writeable() && !m_outBuf.isEmpty())
+    {
+      uint8_t c;
+      m_outBuf.dequeue(&c);
+      m_serial.putc((char)c);
+    }
+    static volatile int i=0;
+    m_serial.writePacket(); //Start packet write
+  }
+  m_spaceSphre.release(); //Force exiting the waiting state
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/serial/usb/USBSerialStream.h	Tue Jun 26 13:44:59 2012 +0000
@@ -0,0 +1,77 @@
+/* USBSerialStream.h */
+/*
+Copyright (C) 2011 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.
+*/
+
+#ifndef USBSERIALSTREAM_H_
+#define USBSERIALSTREAM_H_
+
+
+#include "core/fwk.h"
+
+#include "USB3GModule/IUSBHostSerial.h"
+#include "USB3GModule/IUSBHostSerialListener.h"
+
+#include "rtos.h"
+#include "core/MtxCircBuffer.h"
+
+/* Input Serial Stream for USB virtual serial ports interfaces
+This class is not thread-safe, except for the *Abort() methods that can be called by any thread/ISR
+*/
+#define CIRCBUF_SIZE 255
+class USBSerialStream : public IOStream, IUSBHostSerialListener
+{
+public:
+  USBSerialStream(IUSBHostSerial& serial);
+  /*virtual*/ ~USBSerialStream();
+
+  //0 for non-blocking (returns immediately), osWaitForever for infinite blocking
+  virtual int read(uint8_t* buf, size_t* pLength, size_t maxLength, uint32_t timeout=osWaitForever);
+  virtual size_t available();
+  virtual int waitAvailable(uint32_t timeout=osWaitForever); //Wait for data to be available
+  virtual int abortRead(); //Abort current reading (or waiting) operation
+
+
+  //0 for non-blocking (returns immediately), osWaitForever for infinite blocking
+  virtual int write(uint8_t* buf, size_t length, uint32_t timeout=osWaitForever);
+  virtual size_t space();
+  virtual int waitSpace(uint32_t timeout=osWaitForever); //Wait for space to be available
+  virtual int abortWrite(); //Abort current writing (or waiting) operation
+
+private:
+  IUSBHostSerial& m_serial;
+  volatile bool m_serialTxFifoEmpty;
+
+  void setupReadableISR(bool en);
+  virtual void readable(); //Callback from m_serial when new data is available
+
+  Semaphore m_availableSphre; //Used for signalling
+
+  void setupWriteableISR(bool en);
+  virtual void writeable(); //Callback from m_serial when new space is available
+
+  Semaphore m_spaceSphre; //Used for signalling
+
+  MtxCircBuffer<uint8_t, CIRCBUF_SIZE + 1> m_inBuf;
+  MtxCircBuffer<uint8_t, CIRCBUF_SIZE + 1> m_outBuf;
+};
+
+#endif /* USBSERIALSTREAM_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sms/SMSInterface.cpp	Tue Jun 26 13:44:59 2012 +0000
@@ -0,0 +1,390 @@
+/* SMSInterface.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__ 4
+#ifndef __MODULE__
+#define __MODULE__ "SMSInterface.cpp"
+#endif
+
+#include "core/fwk.h"
+
+#include "SMSInterface.h"
+
+#include <cstdio>
+
+#define DEFAULT_TIMEOUT 10000
+
+SMSInterface::SMSInterface(ATCommandsInterface* pIf) : m_pIf(pIf), m_msg(NULL), m_maxMsgLength(0), m_msisdn(NULL), /*m_msgCount(0),*/
+m_msgRefListCount(0), m_needsUpdate(true), m_state(SMS_IDLE)
+{
+  m_pIf->registerEventsHandler(this); //Add us to the unsolicited result codes handlers
+}
+
+int SMSInterface::init()
+{
+  DBG("Set format");
+  //Set Text mode format
+  int ret = m_pIf->executeSimple("AT+CMGF=1", NULL, DEFAULT_TIMEOUT);
+  if(ret != OK)
+  {
+    return NET_PROTOCOL;
+  }
+
+  DBG("Setup new messages indication");
+  //Setup new messages indication
+  ret = m_pIf->executeSimple("AT+CNMI=2,1,0,0,0", NULL, DEFAULT_TIMEOUT);
+  if(ret != OK)
+  {
+    return NET_PROTOCOL;
+  }
+
+  DBG("Try to fetch inbox");
+  m_inboxMtx.lock();
+  if( m_needsUpdate )
+  {
+    ret = updateInbox(); //Fetch existing messages references
+    if(ret)
+    {
+      m_inboxMtx.unlock();
+      return NET_PROTOCOL;
+    }
+  }
+  m_inboxMtx.unlock();
+
+  DBG("Initialization done");
+  return OK;
+}
+
+int SMSInterface::send(const char* number, const char* message)
+{
+  if( strlen(number) > 16 )
+  {
+    return NET_INVALID; //Number too long to match 3GPP spec
+  }
+
+  int ret;
+
+  //Prepare infos
+  m_state = SMS_SEND_CMD_SENT;
+  m_msg = (char*) message;
+
+  DBG("Send SM");
+  //Send command
+  char cmd[32];
+  std::sprintf(cmd, "AT+CMGS=\"%s\"", number);
+  ret = m_pIf->execute(cmd, this, NULL, DEFAULT_TIMEOUT);
+
+  if( (ret != OK) || (m_state != SMS_CMD_PROCESSED) )
+  {
+    WARN("ret %d, state %d", ret, m_state);
+    m_state = SMS_IDLE;
+    return NET_PROTOCOL;
+  }
+
+  DBG("SM sent");
+  m_state = SMS_IDLE;
+  return OK;
+}
+
+
+int SMSInterface::get(char* number, char* message, size_t maxLength)
+{
+  if( maxLength < 1  )
+  {
+    return NET_INVALID; //Buffer too short
+  }
+
+  int ret;
+
+  DBG("Get next message");
+  m_inboxMtx.lock();
+  if(m_msgRefListCount == 0 && m_needsUpdate)
+  {
+    ret = updateInbox();
+    if (ret)
+    {
+      m_inboxMtx.unlock();
+      return ret;
+    }
+  }
+
+  if(m_msgRefListCount == 0)
+  {
+    m_inboxMtx.unlock();
+    return NET_EMPTY; //No message to read
+  }
+
+  //Prepare infos
+  m_state = SMS_GET_CMD_SENT;
+  m_msisdn = (char*) number;
+  m_msg = (char*) message;
+  m_maxMsgLength = maxLength;
+
+  DBG("Get SMS");
+  //List command
+  char cmd[32];
+  std::sprintf(cmd, "AT+CMGR=%d", m_msgRefList[0]);
+  ret = m_pIf->execute(cmd, this, NULL, DEFAULT_TIMEOUT);
+  if( ret != OK )
+  {
+    WARN("AT+CMGR returned %d", ret);
+    m_state = SMS_IDLE;
+    m_inboxMtx.unlock();
+    return NET_PROTOCOL;
+  }
+
+  if (m_state != SMS_CMD_PROCESSED)
+  {
+    m_state = SMS_IDLE;
+    m_inboxMtx.unlock();
+    return NET_EMPTY;
+  }
+
+  m_state = SMS_IDLE;
+
+  DBG("Deleting message");
+  //Delete message from outbox
+  std::sprintf(cmd, "AT+CMGD=%d", m_msgRefList[0]);
+  ret = m_pIf->executeSimple(cmd, NULL, DEFAULT_TIMEOUT);
+  if(ret != OK)
+  {
+    m_inboxMtx.unlock();
+    WARN("Could not delete message");
+  }
+
+  //Remove message from list
+  std::memmove(m_msgRefList, m_msgRefList+1, m_msgRefListCount-1);
+  m_msgRefListCount--;
+
+  m_inboxMtx.unlock();
+
+  return OK;
+}
+
+
+int SMSInterface::getCount(size_t* pCount)
+{
+  int ret;
+
+  m_inboxMtx.lock();
+  if( m_needsUpdate )
+  {
+    ret = updateInbox();
+    if(ret)
+    {
+      m_inboxMtx.unlock();
+      return NET_PROTOCOL;
+    }
+  }
+
+  *pCount = m_msgRefListCount;
+  m_inboxMtx.unlock();
+
+  return OK;
+}
+
+
+/*virtual*/ int SMSInterface::onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
+{
+  if(m_state == SMS_SEND_CMD_SENT)
+  {
+    if( std::sscanf(line, "+CMGS: %*d") == 0 )
+    {
+      DBG("SM sent");
+      m_state = SMS_CMD_PROCESSED;
+    }
+  }
+  else if(m_state == SMS_GET_CMD_SENT)
+  {
+    DBG("Header: %s", line);
+    if( std::sscanf(line, "+CMGR: %*[^,],\"%16[^\"]\"", m_msisdn) == 1 ) //Get message ref
+    {
+      m_state = SMS_GET_HDR_RECEIVED;
+    }
+  }
+  else if(m_state == SMS_GET_HDR_RECEIVED)
+  {
+    DBG("Message: %s", line);
+    size_t cpyLen = MIN( std::strlen(line), m_maxMsgLength - 1 );
+    std::memcpy( m_msg, line, cpyLen );
+    m_msg[cpyLen] = '\0';
+    m_state = SMS_CMD_PROCESSED;
+  }
+  else if(m_state == SMS_GET_COUNT_CMD_SENT)
+  {
+    DBG("Header: %s", line);
+    int msgRef;
+    if( std::sscanf(line, "+CMGL: %d", &msgRef) == 1 )
+    {
+      m_state = SMS_GET_COUNT_HDR_RECEIVED;
+      //Add message to list
+      if(m_msgRefListCount < MAX_SM)
+      {
+        m_msgRefList[m_msgRefListCount] = msgRef;
+      }
+      m_msgRefListCount++; //Always count message
+      DBG("m_msgRefListCount=%d",m_msgRefListCount);
+    }
+  }
+  else if(m_state == SMS_GET_COUNT_HDR_RECEIVED)
+  {
+    DBG("Message (debug only): %s", line); //For debug only
+    m_state = SMS_GET_COUNT_CMD_SENT;
+  }
+  return OK;
+}
+
+/*virtual*/ int SMSInterface::onNewEntryPrompt(ATCommandsInterface* pInst)
+{
+  if(m_state == SMS_SEND_CMD_SENT)
+  {
+    char* crPtr = strchr(m_msg, CR);
+    if(crPtr != NULL)
+    {
+      int crPos = crPtr - m_msg;
+      //Replace m_inputBuf[crPos] with null-terminating char
+      m_msg[crPos] = '\x0';
+
+      //If there is a CR char, split message there
+
+      //Do print the message
+      int ret = pInst->sendData(m_msg);
+      if(ret)
+      {
+        return ret;
+      }
+
+      char cr[2] = {CR, '\0'};
+      ret = pInst->sendData(cr);
+      if(ret)
+      {
+        return ret;
+      }
+
+      m_msg += crPos;
+
+      if(m_msg[0] == LF)
+      {
+        m_msg++; //Discard LF char as well
+      }
+
+      return NET_MOREINFO;
+    }
+    else
+    {
+      //Do print the message
+      pInst->sendData(m_msg);
+      return OK;
+    }
+  }
+
+  return OK;
+}
+
+/*virtual*/ bool SMSInterface::isATCodeHandled(const char* atCode) //Is this AT code handled
+{
+  DBG("AT code is %s", atCode);
+  if( strcmp("+CMTI", atCode) == 0 )
+  {
+    return true;
+  }
+
+  DBG("Not handled");
+  return false;
+}
+
+/*virtual*/ void SMSInterface::onDispatchStart()
+{
+
+
+}
+
+/*virtual*/ void SMSInterface::onDispatchStop()
+{
+
+}
+
+/*virtual*/ void SMSInterface::onEvent(const char* atCode, const char* evt)
+{
+  if( strcmp("+CMTI", atCode) != 0 )
+  {
+    return; //Not supported
+  }
+
+  DBG("Unsollicited result code: %s - %s", atCode, evt);
+
+  //Get index
+  int msgRef;
+  if( std::sscanf(evt, "\"SM\",%d", &msgRef) == 1 )
+  {
+    DBG("Adding message to list (ref %d)", msgRef);
+    m_inboxMtx.lock();
+    //Add message to list
+    if(m_msgRefListCount < MAX_SM)
+    {
+      m_msgRefList[m_msgRefListCount] = msgRef;
+    }
+    else
+    {
+      m_needsUpdate = true;
+    }
+    m_msgRefListCount++; //Always count message
+    m_inboxMtx.unlock();
+  }
+}
+
+int SMSInterface::updateInbox()
+{
+  //Get memory indexes of unread messages
+  m_state = SMS_GET_COUNT_CMD_SENT;
+
+  DBG("Updating inbox");
+  m_msgRefListCount = 0; //Reset list
+
+  int ret = m_pIf->execute("AT+CMGL=\"REC UNREAD\"", this, NULL, DEFAULT_TIMEOUT);
+  if( ret != OK )
+  {
+    WARN("AT+CMGL returned %d", ret);
+    m_state = SMS_IDLE;
+    m_msgRefListCount = 0; //List could be invalid
+    m_needsUpdate = true;
+    return NET_PROTOCOL;
+  }
+
+  DBG("%d incoming messages in inbox", m_msgRefListCount);
+
+  if( m_msgRefListCount > MAX_SM )
+  {
+    m_needsUpdate = true;
+  }
+  else
+  {
+    m_needsUpdate = false;
+  }
+
+  m_state = SMS_IDLE;
+
+  return OK;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sms/SMSInterface.h	Tue Jun 26 13:44:59 2012 +0000
@@ -0,0 +1,105 @@
+/* SMSInterface.h */
+/*
+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.
+*/
+
+#ifndef SMSINTERFACE_H_
+#define SMSINTERFACE_H_
+
+#include "core/fwk.h"
+
+#include "rtos.h"
+
+#include "drv/at/ATCommandsInterface.h"
+
+#define MAX_SM 8
+
+/** Component to use the Short Messages Service (SMS)
+ *
+ */
+class SMSInterface : protected IATCommandsProcessor, IATEventsHandler
+{
+public:
+  /** Create SMSInterface instance
+     @param pIf Pointer to the ATCommandsInterface instance to use
+   */
+  SMSInterface(ATCommandsInterface* pIf);
+
+  /** Initialize interface
+    Configure SMS commands & register for SMS-related unsolicited result codes
+   */
+  int init();
+
+  /** Send a SM
+     @param number The receiver's phone number
+     @param message The message to send
+     @return 0 on success, error code on failure
+   */
+  int send(const char* number, const char* message);
+
+
+  /** Receive a SM
+     @param number Pointer to a buffer to store the sender's phone number (must be at least 17 characters-long, including the space for the null-terminating char)
+     @param message Pointer to a buffer to store the the incoming message
+     @param maxLength Maximum message length that can be stored in buffer (including null-terminating character)
+     @return 0 on success, error code on failure
+   */
+  int get(char* number, char* message, size_t maxLength);
+
+
+  /** Get the number of SMs in the incoming box
+     @param pCount pointer to store the number of unprocessed SMs on
+     @return 0 on success, error code on failure
+   */
+  int getCount(size_t* pCount);
+
+protected:
+  //IATCommandsProcessor
+  virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line);
+  virtual int onNewEntryPrompt(ATCommandsInterface* pInst);
+
+  //IATEventsHandler
+  virtual bool isATCodeHandled(const char* atCode); //Is this AT code handled
+  virtual void onDispatchStart();
+  virtual void onDispatchStop();
+  virtual void onEvent(const char* atCode, const char* evt);
+
+  //Updates messages count/references
+  int updateInbox();
+
+private:
+  ATCommandsInterface* m_pIf;
+
+  //Current message
+  char* m_msg;
+  size_t m_maxMsgLength;
+  char* m_msisdn;
+
+  //Messages list
+  int m_msgRefList[MAX_SM];
+  size_t m_msgRefListCount;
+  bool m_needsUpdate;
+  Mutex m_inboxMtx; //To protect concurrent accesses btw the user's thread and the AT thread
+
+  enum { SMS_IDLE, SMS_SEND_CMD_SENT, SMS_GET_CMD_SENT, SMS_GET_HDR_RECEIVED, SMS_GET_COUNT_CMD_SENT, SMS_GET_COUNT_HDR_RECEIVED, SMS_CMD_PROCESSED } m_state;
+};
+
+#endif /* SMSINTERFACE_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ussd/USSDInterface.cpp	Tue Jun 26 13:44:59 2012 +0000
@@ -0,0 +1,152 @@
+/* USSDInterface.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__ 4
+#ifndef __MODULE__
+#define __MODULE__ "USSDInterface.cpp"
+#endif
+
+#include "core/fwk.h"
+
+#include "USSDInterface.h"
+
+#include <cstdio>
+
+#define DEFAULT_TIMEOUT 10000
+#define USSD_TIMEOUT 15000
+
+USSDInterface::USSDInterface(ATCommandsInterface* pIf) : m_pIf(pIf), m_responseMtx(), m_responseSphre(1), m_result(NULL), m_maxResultLength(0)
+{
+  m_responseSphre.wait(0); //Take ownership of the semaphore
+  m_pIf->registerEventsHandler(this); //Add us to the unsolicited result codes handlers
+}
+
+int USSDInterface::init()
+{
+  DBG("Initialization done");
+  return OK;
+}
+
+int USSDInterface::send(const char* command, char* result, size_t maxLength)
+{
+  if (strlen(command) > 20) //Prevent buffer overflow
+  {
+    return NET_TOOSMALL;
+  }
+
+  m_responseMtx.lock();
+  m_result = result;
+  m_maxResultLength = maxLength;
+  m_responseMtx.unlock();
+
+  m_responseSphre.wait(0); //Make sure there is not a pending result that needs to be discarded
+
+  DBG("Send USSD command & register for unsolicited result codes");
+  //Send USSD command to the network
+  char cmd[32];
+  std::sprintf(cmd, "AT+CUSD=1,\"%s\"", command);
+  int ret = m_pIf->executeSimple(cmd, NULL, DEFAULT_TIMEOUT);
+  if( ret != OK )
+  {
+    return NET_PROTOCOL;
+  }
+
+  //Now wait for response
+  int res = m_responseSphre.wait(USSD_TIMEOUT);
+
+  //Reset data
+  m_responseMtx.lock();
+  m_result = NULL;
+  m_maxResultLength = 0;
+  m_responseMtx.unlock();
+
+  if(res <= 0)
+  {
+    DBG("No result received");
+    ret = m_pIf->executeSimple("AT+CUSD=2", NULL, DEFAULT_TIMEOUT); //Cancel command
+    if( ret != OK )
+    {
+      return NET_PROTOCOL;
+    }
+    return NET_TIMEOUT;
+  }
+
+  DBG("Result received: %s", result);
+
+  return OK;
+
+}
+
+/*virtual*/ bool USSDInterface::isATCodeHandled(const char* atCode) //Is this AT code handled
+{
+  DBG("AT code is %s", atCode);
+  if( strcmp("+CUSD", atCode) == 0 )
+  {
+    return true;
+  }
+
+  DBG("Not handled");
+  return false;
+}
+
+/*virtual*/ void USSDInterface::onDispatchStart()
+{
+
+
+}
+
+/*virtual*/ void USSDInterface::onDispatchStop()
+{
+
+}
+
+/*virtual*/ void USSDInterface::onEvent(const char* atCode, const char* evt)
+{
+  if( strcmp("+CUSD", atCode) != 0 )
+  {
+    return; //Not supported
+  }
+
+  char* pStart = (char*) strchr(evt,'\"');
+  if(pStart==NULL)
+  {
+    return; //Invalid/incomplete response
+  }
+  pStart++; //Point to first char of response
+  char* pEnd = (char*) strchr(pStart,'\"');
+  if(pEnd==NULL)
+  {
+    return; //Invalid/incomplete response
+  }
+  m_responseMtx.lock();
+  if(m_maxResultLength == 0) //No pending command
+  {
+    m_responseMtx.unlock();
+    return;
+  }
+  size_t cpyLen = MIN( pEnd - pStart, m_maxResultLength - 1 );
+  memcpy(m_result, pStart, cpyLen);
+  m_result[cpyLen] = '\0';
+  m_responseMtx.unlock();
+  m_responseSphre.release(); //Signal user thread that response is ready
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ussd/USSDInterface.h	Tue Jun 26 13:44:59 2012 +0000
@@ -0,0 +1,76 @@
+/* USSDInterface.h */
+/*
+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.
+*/
+
+#ifndef USSDINTERFACE_H_
+#define USSDINTERFACE_H_
+
+#include "core/fwk.h"
+
+#include "rtos.h"
+
+#include "drv/at/ATCommandsInterface.h"
+
+/** Component to send/receive Unstructured Supplementary Service Data (USSD)
+ *
+ */
+class USSDInterface : protected IATEventsHandler
+{
+public:
+  /** Create USSDInterface instance
+     @param pIf Pointer to the ATCommandsInterface instance to use
+   */
+  USSDInterface(ATCommandsInterface* pIf);
+
+  /** Initialize interface
+   Configure USSD commands & register for USSD-related unsolicited result codes
+  */
+  int init();
+
+  /** Send a USSD command & wait for its result
+    @param command The command to send
+    @param result Buffer in which to store the result
+    @param maxLength Maximum result length that can be stored in buffer (including null-terminating character)
+    @return 0 on success, error code on failure
+  */
+  int send(const char* command, char* result, size_t maxLength);
+
+protected:
+  //IATEventsHandler
+  virtual bool isATCodeHandled(const char* atCode); //Is this AT code handled
+  virtual void onDispatchStart();
+  virtual void onDispatchStop();
+  virtual void onEvent(const char* atCode, const char* evt);
+
+private:
+  ATCommandsInterface* m_pIf;
+  Mutex m_responseMtx; //To protect concurrent accesses btw the user's thread and the AT thread
+  Semaphore m_responseSphre;
+
+  //Result
+  char* m_result;
+  size_t m_maxResultLength;
+
+};
+
+
+#endif /* USSDINTERFACE_H_ */