USB Host Library for Sprint Dongles

Dependencies:   Socket USBHostWANDongleSprint lwip-sys lwip

Dependents:   SprintUSBModemWebsocketTest SprintUSBModemHTTPClientTest SprintUSBModemNTPClientTest SprintUSBModemSMSTest ... more

Fork of SprintUSBModem_bleedingedge by Donatien Garnier

Files at this revision

API Documentation at this revision

Comitter:
donatien
Date:
Wed Sep 12 09:34:21 2012 +0000
Child:
1:1e847d871409
Commit message:
Initial Commit

Changed in this revision

Socket.lib Show annotated file Show diff for this revision Revisions of this file
SprintUSBModem.cpp Show annotated file Show diff for this revision Revisions of this file
SprintUSBModem.h Show annotated file Show diff for this revision Revisions of this file
USBHostWANDongleSprint_bleedingedge.lib 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
core/IOStream.h Show annotated file Show diff for this revision Revisions of this file
core/MtxCircBuffer.h Show annotated file Show diff for this revision Revisions of this file
core/config.h Show annotated file Show diff for this revision Revisions of this file
core/dbg.cpp Show annotated file Show diff for this revision Revisions of this file
core/dbg.h Show annotated file Show diff for this revision Revisions of this file
core/errors.h Show annotated file Show diff for this revision Revisions of this file
core/fwk.h Show annotated file Show diff for this revision Revisions of this file
ip/IPInterface.cpp Show annotated file Show diff for this revision Revisions of this file
ip/IPInterface.h Show annotated file Show diff for this revision Revisions of this file
ip/LwIPInterface.cpp Show annotated file Show diff for this revision Revisions of this file
ip/LwIPInterface.h Show annotated file 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
lwip-sys.lib Show annotated file Show diff for this revision Revisions of this file
lwip.lib Show annotated file Show diff for this revision Revisions of this file
lwipopts_conf.h Show annotated file 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
socket/bsd_socket.h Show annotated file Show diff for this revision Revisions of this file
socket/netdb.h Show annotated file Show diff for this revision Revisions of this file
socket/netinet/in.h Show annotated file Show diff for this revision Revisions of this file
socket/sys/socket.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Socket.lib	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/Socket/#41e3af01f58e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SprintUSBModem.cpp	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,340 @@
+/* SprintUSBModem.cpp */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * 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__ 3
+#ifndef __MODULE__
+#define __MODULE__ "SprintUSBModem.cpp"
+#endif
+
+#include "core/fwk.h"
+
+#include "SprintUSBModem.h"
+
+SprintUSBModem::SprintUSBModem() : m_dongle(),
+m_atStream(m_dongle.getSerial(1)), m_pppStream(m_dongle.getSerial(0)), m_at(&m_atStream),
+m_sms(&m_at), m_ppp(&m_pppStream), 
+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;
+};
+
+int SprintUSBModem::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;
+  }
+
+  #if USE_ONE_PORT
+  m_smsInit = false; //SMS status reset
+  m_ussdInit = false; //USSD status reset
+  m_linkMonitorInit = false; //Link monitor status reset
+  #endif
+
+  ATCommandsInterface::ATResult result;
+
+  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);
+  }
+
+
+  //Connect
+  DBG("Connecting");
+  #if USE_ONE_PORT
+  m_at.close(); // Closing AT parser
+  m_atOpen = false; //Will need to be reinitialized afterwards
+  #endif
+
+  DBG("Connecting PPP");
+
+  ret = m_ppp.connect();
+  DBG("Result of connect: Err code=%d", ret);
+  return ret;
+}
+
+
+int SprintUSBModem::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);
+
+  #if USE_ONE_PORT
+  ATCommandsInterface::ATResult result;
+  DBG("Starting AT thread");
+  ret = m_at.open();
+  if(ret)
+  {
+    return ret;
+  }
+  #endif
+
+  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
+
+  #if USE_ONE_PORT
+  //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;
+  }
+
+  #if 0
+  m_at.close(); // Closing AT parser
+  DBG("AT Parser closed");
+  #endif
+  #endif
+  return OK;
+}
+
+int SprintUSBModem::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 SprintUSBModem::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 SprintUSBModem::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;
+}
+
+ATCommandsInterface* SprintUSBModem::getATCommandsInterface()
+{
+  return &m_at;
+}
+
+int SprintUSBModem::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;
+  }
+
+  if(m_dongle.getDongleType() == WAN_DONGLE_TYPE_SPRINT598U)
+  {
+    INFO("Using a Sprint 598U Dongle");
+  }
+  else
+  {
+    WARN("Using an Unknown Dongle");
+  }
+
+  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/SprintUSBModem.h	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,103 @@
+/* SprintUSBModem.h */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * 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 SPRINTUSBMODEM_H_
+#define SPRINTUSBMODEM_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"
+
+/** Sprint USB Modem (Sierra Wireless 598U)
+ */
+class SprintUSBModem
+{
+public:
+  /** Create Sprint USB Modem (Sierra Wireless 598U) API instance
+
+   */
+  SprintUSBModem();
+
+  //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);
+
+  /** 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;
+  
+  PPPIPInterface m_ppp;
+
+  bool m_dongleConnected;
+  bool m_ipInit;
+  bool m_smsInit;
+  bool m_atOpen;
+};
+
+
+#endif /* SPRINTUSBMODEM_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostWANDongleSprint_bleedingedge.lib	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/donatien/code/USBHostWANDongleSprint_bleedingedge/#bfed5767d0a5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/at/ATCommandsInterface.cpp	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,802 @@
+/* ATCommandsInterface.cpp */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * 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	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,142 @@
+/* ATCommandsInterface.h */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * 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 4
+
+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_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/IOStream.h	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,61 @@
+/* IOStream.h */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * 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 IOSTREAM_H_
+#define IOSTREAM_H_
+
+#include "fwk.h"
+
+#include "rtos.h"
+
+class IStream
+{
+public:
+  //IStream();
+  //virtual ~IStream();
+
+    //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) = 0;
+    virtual size_t available() = 0;
+    virtual int waitAvailable(uint32_t timeout=osWaitForever) = 0; //Wait for data to be available
+    virtual int abortRead() = 0; //Abort current reading (or waiting) operation
+};
+
+class OStream
+{
+public:
+  //OStream();
+  //virtual ~OStream();
+
+    //0 for non-blocking (returns immediately), osWaitForever for infinite blocking
+    virtual int write(uint8_t* buf, size_t length, uint32_t timeout=osWaitForever) = 0;
+    virtual size_t space() = 0;
+    virtual int waitSpace(uint32_t timeout=osWaitForever) = 0; //Wait for space to be available
+    virtual int abortWrite() = 0; //Abort current writing (or waiting) operation
+};
+
+class IOStream : public IStream, public OStream
+{
+public:
+  //IOStream();
+  //virtual ~IOStream();
+};
+
+
+#endif /* IOSTREAM_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/MtxCircBuffer.h	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,103 @@
+/* MtxCircBuf.h */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * 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 MTXCIRCBUFFER_H
+#define MTXCIRCBUFFER_H
+
+#include "fwk.h"
+
+#include "rtos.h"
+
+//Mutex protected circualr buffer
+template<typename T, int size>
+class MtxCircBuffer
+{
+public:
+  MtxCircBuffer() //:
+      //mtx()
+  {
+    write = 0;
+    read = 0;
+  }
+
+  bool isFull()
+  {
+    mtx.lock();
+    bool r = (((write + 1) % size) == read);
+    mtx.unlock();
+    return r;
+  }
+
+  bool isEmpty()
+  {
+    mtx.lock();
+    bool r = (read == write);
+    mtx.unlock();
+    return r;
+  }
+
+  void queue(T k)
+  {
+    mtx.lock();
+    while (((write + 1) % size) == read) //if (isFull())
+    {
+      /*while((((write + 1) % size) == read))
+      {*/
+        mtx.unlock();
+        Thread::wait(10);
+        mtx.lock();
+      /*}*/
+      //read++;
+      //read %= size;
+    }
+    buf[write++] = k;
+    write %= size;
+    mtx.unlock();
+  }
+
+  uint16_t available()
+  {
+    mtx.lock();
+    uint16_t a = (write >= read) ? (write - read) : (size - read + write);
+    mtx.unlock();
+    return a;
+  }
+
+  bool dequeue(T * c)
+  {
+    mtx.lock();
+    bool empty = (read == write);
+    if (!empty)
+    {
+      *c = buf[read++];
+      read %= size;
+    }
+    mtx.unlock();
+    return (!empty);
+  }
+
+private:
+  volatile uint16_t write;
+  volatile uint16_t read;
+  volatile T buf[size];
+  Mutex mtx;
+};
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/config.h	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,27 @@
+/* config.h */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * 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 CONFIG_H_
+#define CONFIG_H_
+
+
+//Configuration
+#define AT_THREAD_PRIORITY 0
+
+
+#endif /* CONFIG_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/dbg.cpp	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,127 @@
+/* dbg.cpp */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * 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.
+ */
+
+#include "dbg.h"
+
+#include "mbed.h"
+#include "rtos.h"
+
+#include <cstdio>
+#include <cstdarg>
+
+using namespace std;
+
+static Serial debug_pc(USBTX, USBRX);
+
+static char debug_newline[3];
+
+static void debug_lock(bool set)
+{
+  static Mutex* mtx = new Mutex(); //Singleton runtime initialisation to avoid static initialisation chaos problems
+  static bool init = false;
+  if(set)
+  {
+    mtx->lock();
+    if(!init)
+    {
+      strncpy( debug_newline, "\n", 2 );
+      printf("[START]\n");
+      fflush(stdout);
+      init = true;
+    }
+  }
+  else
+  {
+    mtx->unlock();
+  }
+}
+
+void debug_init()
+{
+  debug_lock(true); //Force init
+  debug_lock(false);
+}
+
+void debug_set_newline(const char* newline)
+{
+  debug_lock(true);
+  strncpy( debug_newline, newline, 2 );
+  debug_newline[2] = '\0';
+  debug_lock(false);
+}
+
+void debug_set_speed(int speed)
+{
+  debug_pc.baud(speed);
+}
+
+void debug(int level, const char* module, int line, const char* fmt, ...)
+{
+  debug_lock(true);
+  switch(level)
+  {
+  default:
+  case 1:
+    printf("[ERROR]");
+    break;
+  case 2:
+    printf("[WARN]");
+    break;
+  case 3:
+    printf("[INFO]");
+    break;
+  case 4:
+    printf("[DBG]");
+    break;
+  }
+
+  printf(" Module %s - Line %d: ", module, line);
+
+  va_list argp;
+
+  va_start(argp, fmt);
+  vprintf(fmt, argp);
+  va_end(argp);
+
+  printf(debug_newline);
+
+  fflush(stdout);
+
+  debug_lock(false);
+
+}
+
+void debug_error(const char* module, int line, int ret)
+{
+  debug_lock(true);
+  printf("[RC] Module %s - Line %d : Error %d\n", module, line, ret);
+  fflush(stdout);
+  debug_lock(false);
+}
+
+void debug_exact(const char* fmt, ...)
+{
+  debug_lock(true);
+  va_list argp;
+
+  va_start(argp, fmt);
+  vprintf(fmt, argp);
+  va_end(argp);
+  debug_lock(false);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/dbg.h	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,79 @@
+/* dbg.h */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * 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 DBG_H_
+#define DBG_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+void debug_init(void);
+void debug(int level, const char* module, int line, const char* fmt, ...);
+void debug_set_newline(const char* newline);
+void debug_set_speed(int speed);
+void debug_error(const char* module, int line, int ret);
+void debug_exact(const char* fmt, ...);
+
+#define DBG_INIT() do{ debug_init(); }while(0)
+
+#define DBG_SET_NEWLINE( x ) do{ debug_set_newline(x); }while(0)
+
+#define DBG_SET_SPEED( x ) do{ debug_set_speed(x); }while(0)
+
+#if __DEBUG__ > 0
+#ifndef __MODULE__
+#error "__MODULE__ must be defined"
+#endif
+#endif
+
+#if __DEBUG__ >= 1
+#define ERR(...) do{ debug(1, __MODULE__, __LINE__, __VA_ARGS__); }while(0)
+#else
+#define ERR(...) do{ }while(0)
+#endif
+
+#if __DEBUG__ >= 2
+#define WARN(...) do{ debug(2, __MODULE__, __LINE__, __VA_ARGS__); }while(0)
+#else
+#define WARN(...) do{ }while(0)
+#endif
+
+#if __DEBUG__ >= 3
+#define INFO(...) do{ debug(3, __MODULE__, __LINE__, __VA_ARGS__); }while(0)
+#define CHECK(ret) do{ if(ret){ debug_error(__MODULE__, __LINE__, ret); } }while(0)
+#else
+#define INFO(...) do{ }while(0)
+#define CHECK(ret) do{ }while(0)
+#endif
+
+#if __DEBUG__ >= 4
+#define DBG(...) do{ debug(4, __MODULE__, __LINE__, __VA_ARGS__); }while(0)
+#define DBGX(...) do{ debug_exact(__VA_ARGS__); }while(0)
+#else
+#define DBG(...) do{ }while(0)
+#define DBGX(...) do{ }while(0)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DBG_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/errors.h	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,47 @@
+/* errors.h */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * 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 ERRORS_H_
+#define ERRORS_H_
+
+/** \page Network-related errors */
+
+#define OK 0 //No error
+
+#define NET_FULL 1 //>All available resources are already used
+#define NET_EMPTY 2 //>No resource
+#define NET_NOTFOUND 3 //>Element cannot be found
+#define NET_INVALID 4 //>Invalid
+#define NET_CONTEXT 5 //>Called in a wrong context (eg during an interrupt)
+#define NET_TIMEOUT 6 //>Timeout
+#define NET_UNKNOWN 7 //>Unknown error
+#define NET_OVERFLOW 8 //>Overflow
+#define NET_PROCESSING 9 //>Command is processing
+#define NET_INTERRUPTED 10 //>Current operation has been interrupted
+#define NET_MOREINFO 11 //>More info on this error can be retrieved elsewhere (eg in a parameter passed as ptr)
+#define NET_ABORT 12 //>Current operation must be aborted
+#define NET_DIFF 13 //>Items that should match are different
+#define NET_AUTH 14 //>Authentication failed
+#define NET_PROTOCOL 15 //>Protocol error
+#define NET_OOM 16 //>Out of memory
+#define NET_CONN 17 //>Connection error
+#define NET_CLOSED 18 //>Connection was closed by remote end
+#define NET_TOOSMALL 19 //>Buffer is too small
+
+#endif /* ERRORS_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/fwk.h	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,61 @@
+/* fwk.h */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * 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 FWK_H_
+#define FWK_H_
+
+#include "config.h"
+
+#include "string.h"
+//using namespace std;
+
+#include "stdint.h"
+typedef unsigned int size_t;
+
+#ifndef __cplusplus
+//boolean type compatibility
+typedef byte bool;
+#define true 1
+#define false 0
+#endif
+
+#ifndef NULL
+#define NULL ((void*)0)
+#endif
+
+#define CR '\x0D'
+#define LF '\x0A'
+#define GD '\x3E'
+#define BRK '\x1A'
+
+//Custom utility classes
+#include "IOStream.h"
+//#include "String.h"
+
+//Error codes
+#include "errors.h"
+
+//Debug
+#include "dbg.h"
+
+//Utility macros
+#define MIN(x,y) (((x)<(y))?(x):(y))
+#define MAX(x,y) (((x)>(y))?(x):(y))
+
+#endif /* FWK_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ip/IPInterface.cpp	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,81 @@
+/* IPInterface.cpp */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * 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.
+ */
+
+#include "core/fwk.h"
+
+#include "IPInterface.h"
+
+#include <cstring> //For strcpy
+
+
+IPInterface::IPInterface()
+{
+
+}
+
+/*virtual*/ IPInterface::~IPInterface()
+{
+
+}
+
+void IPInterface::registerAsDefaultInterface() //First come, first served
+{
+  s_pDefaultInterface = this;
+}
+
+void IPInterface::unregisterAsDefaultInterface() //Must be called before inst is destroyed to avoid invalid ptr fault
+{
+  s_pDefaultInterface = NULL;
+}
+
+/*static*/ IPInterface* IPInterface::getDefaultInterface() //For use by TCP, UDP sockets library
+{
+  return s_pDefaultInterface;
+}
+
+/*static*/ IPInterface* IPInterface::s_pDefaultInterface = NULL;
+
+
+char* IPInterface::getIPAddress() //Get IP Address as a string ('a.b.c.d')
+{
+  if(isConnected())
+  {
+    return m_ipAddr;
+  }
+  else
+  {
+    return NULL;
+  }
+}
+
+bool IPInterface::isConnected() //Is the interface connected?
+{
+  return m_connected;
+}
+
+void IPInterface::setIPAddress(char* ipAddr)
+{
+  std::strcpy(m_ipAddr, ipAddr); //Let's trust the derived class not to buffer overflow us
+}
+
+void IPInterface::setConnected(bool connected)
+{
+  m_connected = connected;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ip/IPInterface.h	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,60 @@
+/* IPInterface.h */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * 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 IPINTERFACE_H_
+#define IPINTERFACE_H_
+
+#include "core/fwk.h"
+
+/** Generic IP-based network interface
+ *
+ */
+class IPInterface
+{
+public:
+    IPInterface();
+    virtual ~IPInterface();
+
+    //int init(); //Initialize interface; no connection should be performed at this stage
+    virtual int connect() = 0; //Do connect the interface
+    virtual int disconnect() = 0;
+    //It is encouraged that the derived class implement a "setup(...)" function to configure the interface before the connection
+    
+    char* getIPAddress(); //Get IP Address as a string ('a.b.c.d')
+    bool isConnected(); //Is the interface connected?
+
+    static IPInterface* getDefaultInterface(); //For use by TCP, UDP sockets library
+
+    //WARN: Implementation will have to be more careful in case of multiple interfaces (or implement a routing protocol based on local IP addresses differentiation)
+    void registerAsDefaultInterface(); //First come, first served
+    void unregisterAsDefaultInterface(); //Must be called before inst is destroyed to avoid invalid ptr fault
+
+protected:
+    //Must be called by subclasses
+    void setIPAddress(char* ipAddr);
+    void setConnected(bool connected);
+
+private:
+    char m_ipAddr[16];
+    bool m_connected;
+
+    static IPInterface* s_pDefaultInterface;
+};
+
+#endif /* IPINTERFACE_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ip/LwIPInterface.cpp	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,52 @@
+/* LwIPInterface.cpp */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * 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.
+ */
+
+
+#include "core/fwk.h"
+
+#include "LwIPInterface.h"
+
+extern "C" {
+#include "lwip/init.h"
+#include "lwip/tcpip.h"
+}
+
+LwIPInterface::LwIPInterface() : IPInterface(), m_rdySphre(1)
+{
+  m_rdySphre.wait();
+}
+
+LwIPInterface::~LwIPInterface()
+{
+
+}
+
+int LwIPInterface::init() //Init LwIP-specific stuff, create the right bindings, etc
+{
+  //lwip_init(); //All LwIP initialisation functions called on a per-module basis (according to lwipopts.h)
+  tcpip_init(LwIPInterface::tcpipRdyCb, this); //Start TCP/IP processing thread
+  m_rdySphre.wait(); //Wait for callback to produce resource
+  return OK;
+}
+
+/*static*/ void LwIPInterface::tcpipRdyCb(void* ctx) //Result of TCP/IP thread launch
+{
+  LwIPInterface* pIf = (LwIPInterface*) ctx;
+  pIf->m_rdySphre.release();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ip/LwIPInterface.h	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,44 @@
+/* LwIPInterface.h */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * 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 LWIPINTERFACE_H_
+#define LWIPINTERFACE_H_
+
+#include "core/fwk.h"
+#include "IPInterface.h"
+
+#include "rtos.h"
+
+/** LwIP-based network interface
+ *
+ */
+class LwIPInterface : public IPInterface
+{
+public:
+    LwIPInterface();
+    virtual ~LwIPInterface();
+
+    int init(); //Init LwIP-specific stuff, create the right bindings, etc
+    
+private:
+    static void tcpipRdyCb(void* ctx); //Result of TCP/IP thread launch
+    Semaphore m_rdySphre;
+};
+
+#endif /* LWIPINTERFACE_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ip/PPPIPInterface.cpp	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,442 @@
+/* PPPIPInterface.cpp */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * 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__ "PPPIPInterface.cpp"
+#endif
+
+#include "core/fwk.h"
+#include "rtos.h"
+
+#include "PPPIPInterface.h"
+
+#define MSISDN "#777"
+//TODO Pass this as parameter (*99# is used by GSM systems, #777 by CDMA systems--well at least Sprint!) 
+
+#define CONNECT_CMD "ATD " MSISDN "\x0D"
+#define EXPECTED_RESP CONNECT_CMD "\x0D" "\x0A" "CONNECT" "\x0D" "\x0A"
+#define EXPECTED_RESP_DATARATE CONNECT_CMD "\x0D" "\x0A" "CONNECT %d" "\x0D" "\x0A"
+#define EXPECTED_RESP_MIN_LEN 20
+#define OK_RESP "\x0D" "\x0A" "OK" "\x0D" "\x0A"
+#define ESCAPE_SEQ "+++"
+#define HANGUP_CMD "ATH" "\x0D"
+#define NO_CARRIER_RESP "\x0D" "\x0A" "NO CARRIER" "\x0D" "\x0A"
+extern "C" {
+#include "lwip/ip_addr.h"
+#include "lwip/inet.h"
+#include "netif/ppp/ppp.h"
+}
+
+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()
+{
+  int ret;
+  char buf[32];
+  size_t len;
+  DBG("Trying to connect with PPP");
+  
+  cleanupLink();
+  
+  DBG("Sending %s", CONNECT_CMD);
+  
+  ret = m_pStream->write((uint8_t*)CONNECT_CMD, strlen(CONNECT_CMD), osWaitForever);
+  if( ret != OK )
+  {
+    return NET_UNKNOWN;
+  }
+  
+  DBG("Expect %s", EXPECTED_RESP);
+    
+  len = 0;
+  size_t readLen;
+  ret = m_pStream->read((uint8_t*)buf + len, &readLen, EXPECTED_RESP_MIN_LEN, 10000);
+  if( ret != OK )
+  {
+    return NET_UNKNOWN;
+  }
+  len += readLen;
+  while( (len < EXPECTED_RESP_MIN_LEN) || (buf[len-1] != LF) )
+  {
+    ret = m_pStream->read((uint8_t*)buf + len, &readLen, 1, 10000);
+    if( ret != OK )
+    {
+      return NET_UNKNOWN;
+    }
+    len += readLen;
+  }
+  
+  buf[len]=0;
+  
+  DBG("Got %s[len %d]", buf, len);
+  
+  int datarate = 0;
+  if( (sscanf( buf, EXPECTED_RESP_DATARATE, &datarate ) != 1) && (strcmp(EXPECTED_RESP, buf) != 0) )
+  {
+    //Discard buffer
+    do //Clear buf
+    {
+      ret = m_pStream->read((uint8_t*)buf, &len, 32, 0);
+    } while( (ret == OK) && (len > 0) );
+    return NET_CONN;
+  }
+      
+  DBG("Transport link open");
+  if(datarate != 0)
+  {
+    DBG("Datarate: %d bps", datarate);
+  }
+  m_linkStatusSphre.wait(0);
+  if((m_pppd != -1) && (m_pppErrCode == 0)) //Already connected
+  {
+    return NET_INVALID;
+  }
+  
+  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
+  }
+  
+  DBG("Sending %s", ESCAPE_SEQ);
+  
+  ret = m_pStream->write((uint8_t*)ESCAPE_SEQ, strlen(ESCAPE_SEQ), osWaitForever);
+  if( ret != OK )
+  {
+    return NET_UNKNOWN;
+  }
+  
+  cleanupLink();
+  
+  return OK;
+}
+
+
+int PPPIPInterface::cleanupLink()
+{
+  int ret;
+  char buf[32];
+  size_t len;
+  
+  do //Clear buf
+  {
+    ret = m_pStream->read((uint8_t*)buf, &len, 32, 100);
+    if(ret == OK)
+    {
+      buf[len] = '\0';
+      DBG("Got %s", buf);
+    }
+  } while( (ret == OK) && (len > 0) );
+  
+  DBG("Sending %s", HANGUP_CMD);
+  
+  ret = m_pStream->write((uint8_t*)HANGUP_CMD, strlen(HANGUP_CMD), osWaitForever);
+  if( ret != OK )
+  {
+    return NET_UNKNOWN;
+  }
+     
+  size_t readLen;
+  
+  //Hangup
+  DBG("Expect %s", HANGUP_CMD);
+
+  len = 0;
+  while( len < strlen(HANGUP_CMD) )
+  {
+    ret = m_pStream->read((uint8_t*)buf + len, &readLen, strlen(HANGUP_CMD) - len, 100);
+    if( ret != OK )
+    {
+      break;
+    }
+    len += readLen;
+    /////
+    buf[len]=0;
+    DBG("Got %s", buf);
+  }
+  
+  buf[len]=0;
+  
+  DBG("Got %s[len %d]", buf, len);
+  
+  //OK response
+  DBG("Expect %s", OK_RESP);
+
+  len = 0;
+  while( len < strlen(OK_RESP) )
+  {
+    ret = m_pStream->read((uint8_t*)buf + len, &readLen, strlen(OK_RESP) - len, 100);
+    if( ret != OK )
+    {
+      break;
+    }
+    len += readLen;
+    /////
+    buf[len]=0;
+    DBG("Got %s", buf);
+  }
+  
+  buf[len]=0;
+  
+  DBG("Got %s[len %d]", buf, len);
+  
+  //NO CARRIER event
+  DBG("Expect %s", NO_CARRIER_RESP);
+
+  len = 0;
+  while( len < strlen(NO_CARRIER_RESP) )
+  {
+    ret = m_pStream->read((uint8_t*)buf + len, &readLen, strlen(NO_CARRIER_RESP) - len, 100);
+    if( ret != OK )
+    {
+      break;
+    }
+    len += readLen;
+    /////
+    buf[len]=0;
+    DBG("Got %s", buf);
+  }
+  
+  buf[len]=0;
+  
+  DBG("Got %s[len %d]", buf, len);
+  
+  do //Clear buf
+  {
+    ret = m_pStream->read((uint8_t*)buf, &len, 32, 100);
+    if(ret == OK)
+    {
+      buf[len] = '\0';
+      DBG("Got %s", buf);
+    }
+  } while( (ret == OK) && (len > 0) );
+  
+  
+  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));
+    pIf->setConnected(true);
+    pIf->setIPAddress(inet_ntoa(addrs->our_ipaddr));
+    break;
+  case PPPERR_CONNECT: //Connection lost
+    WARN("Connection lost/terminated");
+    pIf->setConnected(false);
+    break;
+  case PPPERR_AUTHFAIL: //Authentication failed
+    WARN("Authentication failed");
+    pIf->setConnected(false);
+    break;
+  case PPPERR_PROTOCOL: //Protocol error
+    WARN("Protocol error");
+    pIf->setConnected(false);
+    break;
+  case PPPERR_USER:
+    WARN("Disconnected by user");
+    pIf->setConnected(false);
+    break;
+  default:
+    WARN("Unknown error (%d)", errCode);
+    pIf->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");
+}
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ip/PPPIPInterface.h	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,65 @@
+/* PPPIPInterface.h */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * 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:
+    int cleanupLink();
+
+    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/lwip-sys.lib	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/lwip-sys/#b409691fb352
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwip.lib	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/lwip/#00bf89892c76
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwipopts_conf.h	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,25 @@
+/* lwipopts.h */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * 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_CONF_H_
+#define LWIPOPTS_CONF_H_
+ 
+#define LWIP_TRANSPORT_PPP 1
+
+#endif /* LWIPOPTS_CONF_H_ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/serial/io/IOSerialStream.cpp	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,253 @@
+/* IOSerialStream.cpp */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * 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", 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 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", ret);
+    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", ret);
+        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	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,72 @@
+/* IOSerialStream.h */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * 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	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,236 @@
+/* USBSerialStream.cpp */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * 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 a = available(); //Prevent macro issues
+  int readLen = MIN( a, 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?
+  {
+    while( m_availableSphre.wait(0) > 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");
+  while( m_availableSphre.wait(0) > 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", ret);
+      return ret;
+    }
+    int s = space(); //Prevent macro issues
+    int writeLen = MIN( s, length );
+    DBG("Writing %d chars", writeLen);
+    setupWriteableISR(false);
+    while(writeLen)
+    {
+      m_outBuf.queue(*buf);
+      buf++;
+      length--;
+      writeLen--;
+    }
+    //If m_serial tx fifo is empty we need to start the packet write
+    if( m_outBuf.available() && m_serialTxFifoEmpty )
+    {
+      writeable();
+    }
+    setupWriteableISR(true);
+  } while(length);
+
+  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?
+  {
+    while( m_spaceSphre.wait(0) > 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;
+  }
+  while( m_spaceSphre.wait(0) > 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);
+    }
+    m_serial.writePacket(); //Start packet write
+  }
+  if(!m_outBuf.isFull())
+  {
+    m_spaceSphre.release(); //Force exiting the waiting state
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/serial/usb/USBSerialStream.h	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,73 @@
+/* USBSerialStream.h */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * 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 127
+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	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,386 @@
+/* SMSInterface.cpp */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * 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
+#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	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,101 @@
+/* SMSInterface.h */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * 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 "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/socket/bsd_socket.h	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,34 @@
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * 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 BSD_SOCKET_H_
+#define BSD_SOCKET_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "socket/sys/socket.h" //Must conform to <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html>
+#include "socket/netinet/in.h" //Must conform to <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html>
+#include "socket/netdb.h"      //Must conform to <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netdb.h.html>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BSD_SOCKET_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/socket/netdb.h	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,47 @@
+/* netdb.h */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * 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 NETDB_H_
+#define NETDB_H_
+
+#include "lwip/netdb.h"
+
+//DNS
+
+inline struct hostent *gethostbyname(const char *name)
+{
+  return lwip_gethostbyname(name);
+}
+
+inline int gethostbyname_r(const char *name, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop)
+{
+  return lwip_gethostbyname_r(name, ret, buf, buflen, result, h_errnop);
+}
+
+inline void freeaddrinfo(struct addrinfo *ai)
+{
+  return lwip_freeaddrinfo(ai);
+}
+
+inline int getaddrinfo(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res)
+{
+  return lwip_getaddrinfo(nodename, servname, hints, res);
+}
+
+#endif /* NETDB_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/socket/netinet/in.h	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,25 @@
+/* in.h */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * 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 IN_H_
+#define IN_H_
+
+#include "lwip/inet.h"
+
+#endif /* IN_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/socket/sys/socket.h	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,126 @@
+/* socket.h */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * 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 SOCKET_H_
+#define SOCKET_H_
+
+#include "lwip/sockets.h"
+
+//Sockets
+
+inline int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
+{
+  return lwip_accept(s, addr, addrlen);
+}
+
+inline int bind(int s, const struct sockaddr *name, socklen_t namelen)
+{
+  return lwip_bind(s, name, namelen);
+}
+
+inline int shutdown(int s, int how)
+{
+  return lwip_shutdown(s, how);
+}
+
+inline int getsockname (int s, struct sockaddr *name, socklen_t *namelen)
+{
+  return lwip_getsockname(s, name, namelen);
+}
+
+inline int getpeername (int s, struct sockaddr *name, socklen_t *namelen)
+{
+  return lwip_getpeername(s, name, namelen);
+}
+
+inline int getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen)
+{
+  return lwip_getsockopt(s, level, optname, optval, optlen);
+}
+
+inline int setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen)
+{
+  return lwip_setsockopt(s, level, optname, optval, optlen);
+}
+
+inline int connect(int s, const struct sockaddr *name, socklen_t namelen)
+{
+  return lwip_connect(s, name, namelen);
+}
+
+inline int listen(int s, int backlog)
+{
+  return lwip_listen(s, backlog);
+}
+
+inline int recv(int s, void *mem, size_t len, int flags)
+{
+  return lwip_recv(s, mem, len, flags);
+}
+
+inline int recvfrom(int s, void *mem, size_t len, int flags,
+      struct sockaddr *from, socklen_t *fromlen)
+{
+  return lwip_recvfrom(s, mem, len, flags, from, fromlen);
+}
+
+inline int send(int s, const void *dataptr, size_t size, int flags)
+{
+  return lwip_send(s, dataptr, size, flags);
+}
+
+inline int sendto(int s, const void *dataptr, size_t size, int flags,
+    const struct sockaddr *to, socklen_t tolen)
+{
+  return lwip_sendto(s, dataptr, size, flags, to, tolen);
+}
+
+inline int socket(int domain, int type, int protocol)
+{
+  return lwip_socket(domain, type, protocol);
+}
+
+inline int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
+                struct timeval *timeout)
+{
+  return lwip_select(maxfdp1, readset, writeset, exceptset, timeout);
+}
+
+inline int ioctlsocket(int s, long cmd, void *argp)
+{
+  return lwip_ioctl(s, cmd, argp);
+}
+
+inline int read(int s, void *mem, size_t len)
+{
+  return lwip_read(s, mem, len);
+}
+
+inline int write(int s, const void *dataptr, size_t size)
+{
+  return lwip_write(s, dataptr, size);
+}
+
+inline int close(int s)
+{
+  return lwip_close(s);
+}
+
+#endif /* SOCKET_H_ */