Implementation of 3G USB Modem Huawei E372

Dependents:   PYRN

Files at this revision

API Documentation at this revision

Comitter:
clemounet
Date:
Tue Apr 14 13:27:07 2015 +0000
Parent:
1:fbf17fb09581
Commit message:
.up (working)

Changed in this revision

ATCommandsInterface.cpp Show annotated file Show diff for this revision Revisions of this file
ATCommandsInterface.h Show annotated file Show diff for this revision Revisions of this file
HuaweiUSBModemInitializer.cpp Show diff for this revision Revisions of this file
HuaweiUSBModemInitializer.h Show diff for this revision Revisions of this file
IPInterface.cpp Show diff for this revision Revisions of this file
IPInterface.h Show diff for this revision Revisions of this file
LwIPInterface.cpp Show diff for this revision Revisions of this file
LwIPInterface.h Show diff for this revision Revisions of this file
PPPIPInterface.cpp Show annotated file Show diff for this revision Revisions of this file
PPPIPInterface.h Show annotated file Show diff for this revision Revisions of this file
PyrnUSBModem.cpp Show annotated file Show diff for this revision Revisions of this file
PyrnUSBModem.h Show annotated file Show diff for this revision Revisions of this file
USBSerialStream.cpp Show annotated file Show diff for this revision Revisions of this file
USBSerialStream.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/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
--- a/ATCommandsInterface.cpp	Fri Feb 20 17:15:55 2015 +0000
+++ b/ATCommandsInterface.cpp	Tue Apr 14 13:27:07 2015 +0000
@@ -17,7 +17,12 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#include "dbg.h"
+#define __DEBUG__ 0
+#ifndef __MODULE__
+#define __MODULE__ "ATCommandsInterface.cpp"
+#endif
+#include "MyDebug.h"
+
 #include <cstdio>
 //#include <cstring> //For memset, strstr...
 
@@ -38,10 +43,10 @@
 {
   if( m_open )
   {
-    USB_WARN("AT interface is already open");
+    WARN("AT interface is already open");
     return OK;
   }
-  USB_DBG("Opening AT interface");
+  DBG("Opening AT interface");
   //Start processing
   m_processingThread.signal_set(AT_SIG_PROCESSING_START);
 
@@ -60,34 +65,34 @@
   }
   m_eventsMtx.unlock();
 
-  USB_DBG("AT interface opened");
+  DBG("AT interface opened");
 
   return OK;
 }
 
 //Initialize AT link
-int ATCommandsInterface::init()
+int ATCommandsInterface::init(const char *atInitSeq)
 {
-  USB_DBG("Sending ATZ E1 V1");
+  DBG("Sending %s",atInitSeq);
   //Should we flush m_pStream at this point ???
   int err;
   int tries = 5;
   do
   {
-    err = executeSimple("ATZ E1 V1", NULL, 3000); //Enable echo and verbosity
+    err = executeSimple(atInitSeq, NULL, 3000); //Enable echo and verbosity
     if(err && tries)
     {
-      USB_WARN("No response, trying again");
+      WARN("No response, trying again");
       Thread::wait(1000); //Give dongle time to recover
     }
   } while(err && tries--);
   if( err )
   {
-    USB_ERR("Sending ATZ E1 V1 returned with err code %d", err);
+    ERR("Sending %s returned with err code %d", atInitSeq, err);
     return err;
   }
 
-  USB_DBG("AT interface initialized");
+  DBG("AT interface initialized");
 
   return OK;
 }
@@ -97,11 +102,11 @@
 {
   if( !m_open )
   {
-    USB_WARN("AT interface is already closed");
+    WARN("AT interface is already closed");
     return OK;
   }
 
-  USB_DBG("Closing AT interface");
+  DBG("Closing AT interface");
 
   //Stop processing
   m_processingThread.signal_set(AT_SIG_PROCESSING_STOP);
@@ -127,7 +132,7 @@
   }
   m_eventsMtx.unlock();
 
-  USB_DBG("AT interface closed");
+  DBG("AT interface closed");
   return OK;
 }
 
@@ -143,10 +148,10 @@
 
 int ATCommandsInterface::execute(const char* command, IATCommandsProcessor* pProcessor, ATResult* pResult, uint32_t timeout/*=1000*/)
 {
-  USB_DBG("Executing command %s", command);
+  DBG("Executing command %s", command);
   if(!m_open)
   {
-    USB_WARN("Interface is not open!");
+    WARN("Interface is not open!");
     return NET_INVALID;
   }
 
@@ -159,7 +164,7 @@
   if(evt.status == osEventMail)
   {
     m_AT2Env.free((int*)evt.value.p);
-    USB_WARN("Previous result discarded");
+    WARN("Previous result discarded");
   }
 
   //Send params to the process routine
@@ -175,14 +180,14 @@
 
   Thread::wait(100); //FIXME find stg else
 
-  USB_DBG("Sending command ready signal to AT thread & aborting current blocking read operation");
+  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);
 
-  USB_DBG("Trying to enter abortRead()");
+  DBG("Trying to enter abortRead()");
   //Unlock process routine (abort read)
   m_pStream->abortRead(); //This is thread-safe
 
@@ -196,15 +201,15 @@
     *msg = AT_TIMEOUT;
     m_env2AT.put(msg);
 
-    USB_DBG("Trying to enter abortRead()");
+    DBG("Trying to enter abortRead()");
     //Unlock process routine (abort read)
     m_pStream->abortRead(); //This is thread-safe
 
-    USB_WARN("Command returned no message");
+    WARN("Command returned no message");
     m_transactionMtx.unlock();
     return NET_TIMEOUT;
   }
-  USB_DBG("Command returned with message %d", *msg);
+  DBG("Command returned with message %d", *msg);
 
   m_AT2Env.free((int*)evt.value.p);
 
@@ -216,10 +221,10 @@
   int ret = ATResultToReturnCode(m_transactionResult);
   if(ret != OK)
   {
-    USB_WARN("Command returned AT result %d with code %d", m_transactionResult.result, m_transactionResult.code);
+    WARN("Command returned AT result %d with code %d", m_transactionResult.result, m_transactionResult.code);
   }
 
-  USB_DBG("Command returned successfully");
+  DBG("Command returned successfully");
 
   //Unlock transaction mutex
   m_transactionMtx.unlock();
@@ -265,7 +270,7 @@
   static bool lineDetected = false;
 
   //Block on serial read or incoming command
-  USB_DBG("Trying to read a new line from stream");
+  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)
@@ -276,33 +281,33 @@
   {
     m_inputPos+=readLen;
     m_inputBuf[m_inputPos] = '\0'; //Add null terminating character to ease the use of str* functions
-    USB_DBG("In buffer: [%s]", m_inputBuf);
+    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
   {
-    USB_DBG("Read was interrupted");
+    DBG("Read was interrupted");
     return NET_INTERRUPTED; //0 chars were read
   }
   else if(readLen == 0)
   {
-    USB_DBG("Nothing read");
+    DBG("Nothing read");
     return OK; //0 chars were read
   }
 
-  USB_DBG("Trying to process incoming line");
+  DBG("Trying to process incoming line");
   bool lineProcessed = false;
 
   do
   {
     lineProcessed = false; //Reset flag
 
-    USB_DBG("New iteration");
+    DBG("New iteration");
 
     //Look for a new line
     if(!lineDetected)
     {
-      USB_DBG("No line detected yet");
+      DBG("No line detected yet");
       //Try to look for a starting CRLF
       char* crPtr = strchr(m_inputBuf, CR);
       /*
@@ -318,7 +323,7 @@
       */
       if(crPtr != NULL)
       {
-        USB_DBG("CR char found");
+        DBG("CR char found");
 
 #if 0
         //Discard all preceding characters (can do nothing if m_inputBuf == crPtr)
@@ -338,24 +343,24 @@
               //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)
               {
-                USB_DBG("Beginning of new line found");
+                DBG("Beginning of new line found");
                 //Beginning of a line
                 lineDetected = true; //Move to next state-machine step
               }
               else
               {
                 //End of an unprocessed line
-                USB_WARN("End of unprocessed line");
+                WARN("End of unprocessed line");
               }
               //In both cases discard CRLF
-              USB_DBG("Discarding 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
-              USB_WARN("Unexpected %c char (%02d code) found after CR char", m_inputBuf[1]);
+              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
             }
@@ -366,7 +371,7 @@
         {
           int crPos = crPtr - m_inputBuf;
           int lfOff = 0; //Offset for LF if present
-          USB_DBG("New line found (possible echo of command)");
+          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';
@@ -394,14 +399,14 @@
             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
           }
-          USB_DBG("One line was successfully processed");
+          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
       {
-        USB_DBG("Discarding single LF char");
+        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
       }
@@ -410,7 +415,7 @@
     //Look for the end of line
     if(lineDetected)
     {
-      USB_DBG("Looking for end of line");
+      DBG("Looking for end of line");
       //Try to look for a terminating CRLF
       char* crPtr = strchr(m_inputBuf, CR);
       /*
@@ -428,7 +433,7 @@
 
       if(crPtr != NULL)
       {
-        USB_DBG("CR char found");
+        DBG("CR char found");
         int crPos = crPtr - m_inputBuf;
         //To determine the sequence we need at least 2 chars
         if(m_inputPos - crPos >= 2)
@@ -436,7 +441,7 @@
           //Look for a LF char next to the CR char
           if(m_inputBuf[crPos + 1] == LF)
           {
-            USB_DBG("End of new line found");
+            DBG("End of new line found");
             //This is the end of line
             //Replace m_inputBuf[crPos] with null-terminating char
             m_inputBuf[crPos] = '\0';
@@ -458,13 +463,13 @@
               m_inputPos = m_inputPos - (crPos + 2); //Adjust m_inputPos
             }
 
-            USB_DBG("One line was successfully processed");
+            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
-            USB_WARN("Unexpected %c char (%02d code) found in incoming line", m_inputBuf[crPos + 1]);
+            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
           }
@@ -473,7 +478,7 @@
       }
       else if(greaterThanPtr != NULL)
       {
-        USB_DBG("> char found");
+        DBG("> char found");
         int gdPos = greaterThanPtr - m_inputBuf;
         //To determine the sequence we need at least 2 chars
         if(m_inputPos - gdPos >= 2)
@@ -499,13 +504,13 @@
               return ret;
             }
 
-            USB_DBG("One line was successfully processed");
+            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
-            USB_WARN("Unexpected %c char (%02d code) found in incoming line", m_inputBuf[gdPos + 1]);
+            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
           }
@@ -521,12 +526,12 @@
     //Discard everything
     m_inputPos = 0;
     m_inputBuf[0] = '\0'; //Always have a null-terminating char at start of buffer
-    USB_WARN("Incoming buffer is too short to process incoming line");
+    WARN("Incoming buffer is too short to process incoming line");
     //Look for a new line
     lineDetected = false;
   }
 
-  USB_DBG("Processed every full incoming lines");
+  DBG("Processed every full incoming lines");
 
   return OK;
 }
@@ -534,7 +539,7 @@
 int ATCommandsInterface::trySendCommand()
 {
   osEvent evt = m_env2AT.get(0);
-  USB_DBG("status = %d, msg = %d", evt.status, evt.value.p);
+  DBG("status = %d, msg = %d", evt.status, evt.value.p);
   if(evt.status == osEventMail)
   {
     int* msg = (int*) evt.value.p;
@@ -542,9 +547,9 @@
     {
       if(m_transactionState != IDLE)
       {
-        USB_WARN("Previous command not processed!");
+        WARN("Previous command not processed!");
       }
-      USB_DBG("Sending pending command");
+      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
@@ -561,14 +566,14 @@
 
 int ATCommandsInterface::processReadLine()
 {
-  USB_DBG("Processing read line [%s]", m_inputBuf);
+  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 )
     {
-      USB_DBG("Command echo received");
+      DBG("Command echo received");
       //If so, it means that the following lines will only be solicited results
       m_transactionState = READING_RESULT;
       return OK;
@@ -613,7 +618,7 @@
     //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)
     {
-      USB_DBG("OK result received");
+      DBG("OK result received");
       m_transactionResult.code = 0;
       m_transactionResult.result = ATResult::AT_OK;
       m_transactionState = IDLE;
@@ -624,7 +629,7 @@
     }
     else if(strcmp("ERROR", m_inputBuf) == 0)
     {
-      USB_DBG("ERROR result received");
+      DBG("ERROR result received");
       m_transactionResult.code = 0;
       m_transactionResult.result = ATResult::AT_ERROR;
       m_transactionState = IDLE;
@@ -635,7 +640,7 @@
     }
     else if(strncmp("CONNECT", m_inputBuf, 7 /*=strlen("CONNECT")*/) == 0) //Result can be "CONNECT" or "CONNECT %d", indicating baudrate
     {
-      USB_DBG("CONNECT result received");
+      DBG("CONNECT result received");
       m_transactionResult.code = 0;
       m_transactionResult.result = ATResult::AT_CONNECT;
       m_transactionState = IDLE;
@@ -646,7 +651,7 @@
     }
     else if(strcmp("COMMAND NOT SUPPORT", m_inputBuf) == 0) //Huawei-specific, not normalized
     {
-      USB_DBG("COMMAND NOT SUPPORT result received");
+      DBG("COMMAND NOT SUPPORT result received");
       m_transactionResult.code = 0;
       m_transactionResult.result = ATResult::AT_ERROR;
       m_transactionState = IDLE;
@@ -658,7 +663,7 @@
     else if(strstr(m_inputBuf, "+CME ERROR:") == m_inputBuf) //Mobile Equipment Error
     {
       std::sscanf(m_inputBuf + 12 /* =strlen("+CME ERROR: ") */, "%d", &m_transactionResult.code);
-      USB_DBG("+CME ERROR: %d result received", 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);
@@ -669,7 +674,7 @@
     else if(strstr(m_inputBuf, "+CMS ERROR:") == m_inputBuf) //SIM Error
     {
       std::sscanf(m_inputBuf + 13 /* =strlen("+CME ERROR: ") */, "%d", &m_transactionResult.code);
-      USB_DBG("+CMS ERROR: %d result received", 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);
@@ -679,7 +684,7 @@
     }
     else
     {
-      USB_DBG("Unprocessed result received: '%s'", m_inputBuf);
+      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;
@@ -691,12 +696,12 @@
 
 int ATCommandsInterface::processEntryPrompt()
 {
-  USB_DBG("Calling prompt handler");
+  DBG("Calling prompt handler");
   int ret = m_pTransactionProcessor->onNewEntryPrompt(this); //Here sendData can be called
 
   if( ret != NET_MOREINFO ) //A new prompt is expected
   {
-    USB_DBG("Sending break character");
+    DBG("Sending break character");
     //Send CTRL+Z (break sequence) to exit prompt
     char seq[2] = {BRK, 0x00};
     sendData(seq);
@@ -710,11 +715,11 @@
 {
   //m_inputBuf is cleared at this point (and MUST therefore be empty)
   int dataLen = strlen(data);
-  USB_DBG("Sending raw string of length %d", dataLen);
+  DBG("Sending raw string of length %d", dataLen);
   int ret = m_pStream->write((uint8_t*)data, dataLen, osWaitForever);
   if(ret)
   {
-    USB_WARN("Could not write to stream (returned %d)", ret);
+    WARN("Could not write to stream (returned %d)", ret);
     return ret;
   }
 
@@ -726,7 +731,7 @@
     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)
     {
-      USB_WARN("Could not read from stream (returned %d)", ret);
+      WARN("Could not read from stream (returned %d)", ret);
       m_inputPos = 0; //Reset input buffer state
       m_inputBuf[0] = '\0'; //Always have a null-terminating char at start of buffer
       return ret;
@@ -735,7 +740,7 @@
     if( memcmp(m_inputBuf, data + dataPos, readLen) != 0 )
     {
       //Echo does not match output
-      USB_WARN("Echo does not match output");
+      WARN("Echo does not match output");
       m_inputPos = 0; //Reset input buffer state
       m_inputBuf[0] = '\0'; //Always have a null-terminating char at start of buffer
       return NET_DIFF;
@@ -746,7 +751,7 @@
 
   } while(dataPos < dataLen);
 
-  USB_DBG("String sent successfully");
+  DBG("String sent successfully");
 
   m_inputPos = 0; //Reset input buffer state
   m_inputBuf[0] = '\0'; //Always have a null-terminating char at start of buffer
@@ -783,14 +788,14 @@
 
 void ATCommandsInterface::process() //Processing thread
 {
-  USB_DBG("AT Thread started");
+  DBG("AT Thread started");
   while(true)
   {
-    USB_DBG("AT Processing on hold");
+    DBG("AT Processing on hold");
     m_processingThread.signal_wait(AT_SIG_PROCESSING_START); //Block until the process is started
 
     m_processingMtx.lock();
-    USB_DBG("AT Processing started");
+    DBG("AT Processing started");
     //First of all discard buffer
     int ret;
     size_t readLen;
@@ -801,13 +806,13 @@
     m_inputPos = 0; //Clear input buffer
     do
     {
-      USB_DBG("Trying to read a new line");
+      DBG("Trying to read a new line");
       tryReadLine();
-      USB_DBG("Trying to send a pending command");
+      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();
-    USB_DBG("AT Processing stopped");
+    DBG("AT Processing stopped");
   }
 }
 
--- a/ATCommandsInterface.h	Fri Feb 20 17:15:55 2015 +0000
+++ b/ATCommandsInterface.h	Tue Apr 14 13:27:07 2015 +0000
@@ -20,7 +20,7 @@
 #ifndef ATCOMMANDSINTERFACE_H_
 #define ATCOMMANDSINTERFACE_H_
 
-#include "core/fwk.h"
+#include "fwk.h"
 #include "rtos.h"
 
 #define MAX_AT_EVENTS_HANDLERS 4
@@ -75,7 +75,7 @@
   int open();
 
   //Initialize AT link
-  int init();
+  int init(const char *atInitSeq = "ATZ E1 V1");
 
   //Close connection
   int close();
--- a/HuaweiUSBModemInitializer.cpp	Fri Feb 20 17:15:55 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-
-#include "dbg.h"
-#include "HuaweiUSBModemInitializer.h"
-
-// switch string => "55 53 42 43 00 00 00 00 00 00 00 00 00 00 00 11 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00"
-static uint8_t huawei_E372_switch_packet[] = {
-    0x55, 0x53, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-    0x11, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00
-};
-
-HuaweiE372USBModemInitializer::HuaweiE372USBModemInitializer(USBHost *h): WANDongleInitializer(h) {
-        
-}
-
-bool HuaweiE372USBModemInitializer::switchMode(USBDeviceConnected* pDev) {
-    for (int i = 0; i < pDev->getNbIntf(); i++) {
-        if (pDev->getInterface(i)->intf_class == MSD_CLASS) {
-            USBEndpoint* pEp = pDev->getEndpoint(i, BULK_ENDPOINT, OUT);
-            if ( pEp != NULL )  {
-                USB_DBG("MSD descriptor found on device %p, intf %d, will now try to switch into serial mode", (void *)pDev, i);
-                m_pHost->bulkWrite(pDev, pEp, huawei_E372_switch_packet, 31);
-                return true;
-            }
-        }  
-    }
-    return false;
-}
- USBEndpoint* HuaweiE372USBModemInitializer::getEp(USBDeviceConnected* pDev, int serialPortNumber, bool tx) {
-    return pDev->getEndpoint(serialPortNumber, BULK_ENDPOINT, tx ? OUT : IN, 0);
-}
-
-void HuaweiE372USBModemInitializer::setVidPid(uint16_t vid, uint16_t pid) {
-    if( (vid == getSerialVid()) && (pid == getSerialPid()) ) {
-      m_hasSwitched = true;
-      m_currentSerialIntf = 0;
-      m_endpointsToFetch = 4*2;
-    } else {
-      m_hasSwitched = false;
-      m_endpointsToFetch = 1;
-    }
-}
- 
-bool HuaweiE372USBModemInitializer::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) {
-    if( m_hasSwitched ) {
-        USB_DBG("Interface #%d; Class:%02x; SubClass:%02x; Protocol:%02x", intf_nb, intf_class, intf_subclass, intf_protocol);
-        if( intf_class == VENDSPEC_CLASS ) {
-            // The first 4 Interfaces are parsable.
-            if( m_currentSerialIntf <4 ) {
-                m_currentSerialIntf++;
-                return true;
-            }
-            m_currentSerialIntf++;
-        }
-    } else {
-        // The first 2 Interface are parsable.
-        if( ((intf_nb == 0) || (intf_nb == 1)) && (intf_class == MSD_CLASS) ) {
-            return true;
-        }
-    }
-    return false;
-}
-
-bool HuaweiE372USBModemInitializer::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) {//Must return true if the endpoint will be used
-    if( m_hasSwitched ) {
-        USB_DBG("USBEndpoint on Inteface #%d; Type:%d; Direction:%d", intf_nb, type, dir);
-        if( (type == BULK_ENDPOINT) && m_endpointsToFetch ) {
-            m_endpointsToFetch--;
-            return true;
-        }
-    } else {
-        if( (type == BULK_ENDPOINT) && (dir == OUT) && m_endpointsToFetch ) {
-            m_endpointsToFetch--;
-            return true;
-        }
-    }
-    return false;
-}
--- a/HuaweiUSBModemInitializer.h	Fri Feb 20 17:15:55 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-
-
-#ifndef HUAWEI_USB_BMODEM_INITIALIZER_H
-#define HUAWEI_USB_BMODEM_INITIALIZER_H
-
-#include "mbed.h"
-#include "USBHost/USBHost3GModule/WANDongleInitializer.h"
-
-// For the moment we have only one key
-class HuaweiE372USBModemInitializer: public WANDongleInitializer{
-public:
-    HuaweiE372USBModemInitializer(USBHost *h);
-    virtual uint16_t getMSDVid() { return 0x12D1; }
-    virtual uint16_t getMSDPid() { return 0x1505; }
-    virtual uint16_t getSerialVid() { return 0x12D1; }
-    virtual uint16_t getSerialPid() { return 0x14ac; }
-    virtual bool switchMode(USBDeviceConnected* pDev) ;
-    virtual USBEndpoint* getEp(USBDeviceConnected* pDev, int serialPortNumber, bool tx);
-    virtual int getSerialPortCount() { return 4; }
-    virtual void setVidPid(uint16_t vid, uint16_t pid) ;
-    virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); //Must return true if the interface should be parsed
-    virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) ; //Must return true if the endpoint will be used
-    virtual int getType() { return WAN_DONGLE_TYPE_HUAWEI_E372; }
-    virtual uint8_t getSerialIntf(int index) { return index; }
-private:
-    bool m_hasSwitched;
-    int m_currentSerialIntf;
-    int m_endpointsToFetch;
-};
-
-#endif
\ No newline at end of file
--- a/IPInterface.cpp	Fri Feb 20 17:15:55 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-/* 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() : m_connected(false)
-{
-
-}
-
-/*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;
-}
-
--- a/IPInterface.h	Fri Feb 20 17:15:55 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/* 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_ */
--- a/LwIPInterface.cpp	Fri Feb 20 17:15:55 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/* 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();
-}
--- a/LwIPInterface.h	Fri Feb 20 17:15:55 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/* 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_ */
--- a/PPPIPInterface.cpp	Fri Feb 20 17:15:55 2015 +0000
+++ b/PPPIPInterface.cpp	Tue Apr 14 13:27:07 2015 +0000
@@ -16,25 +16,27 @@
  * 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
+ 
+#define __DEBUG__ 3
 #ifndef __MODULE__
 #define __MODULE__ "PPPIPInterface.cpp"
 #endif
+#include "MyDebug.h"
 
-#include "dbg.h"
-#define DBG(x, ...) USB_DBG(x, __VA_ARGS__)
-
+#include "core/errors.h"
 #include "core/fwk.h"
+#include "core/IOStream.h"
 #include "rtos.h"
 
 #include <cstdio>
 using std::sscanf;
 
 #include "PPPIPInterface.h"
+#include "USBSerialStream.h"
+
+#define PPP_SERIAL_PORT 0
 
 #define MSISDN "*99#"
-
 #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"
@@ -43,418 +45,345 @@
 #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 "lwip/err.h"
-#include "lwip/dns.h"
-
+//#include "lwip/dns.h"
+#include "lwip/tcpip.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();
-}
+PPPIPInterface::PPPIPInterface(USBSerialStream* pStream): 
+    pppStream(pStream),
+    pppSession(0),
+    ipInitiated(false),
+    pppInitiated(false),
+    connected(false) {}
+PPPIPInterface::~PPPIPInterface() { }
 
-/*virtual*/ PPPIPInterface::~PPPIPInterface()
-{
-
+void PPPIPInterface::stackInits(const char* user, const char* pw)  {
+    // LwIP Stuffs
+    if(!ipInitiated) {
+        DBG("LwIP: Init Stack");
+        tcpip_init(PPPIPInterface::tcpipInitDoneCb, this);
+        DBG("LwIP: Wait for setup");
+        while (!ipInitiated)
+            Thread::wait(1);
+        DBG("LwIP: setup done");
+    }
+    // PPP Stuffs
+    if(!pppInitiated) {
+        pppInit();
+        pppSetAuth(PPPAUTHTYPE_ANY, user, pw);
+        pppInitiated = true;
+    }
 }
 
-/*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::dial(void) {
+    int ret;
+    char buf[32];
+    size_t len;
+    
+    DBG("Sending %s", CONNECT_CMD);
+    ret = pppStream->write((uint8_t*)CONNECT_CMD, strlen(CONNECT_CMD), osWaitForever);
+    if( ret != OK )
+        return NET_UNKNOWN;
+    DBG("Expect %s", EXPECTED_RESP);
+    
+    /*
+    size_t readLen;
+    ret = pppStream->read((uint8_t*)buf, &readLen, EXPECTED_RESP_MIN_LEN, 10000);
+    if( ret != OK )
+        return NET_UNKNOWN;
+    
+    DBG("Readed %d chars", readLen);
+    DBG_MEMDUMP("PPPAT",buf,readLen);
+    */
+    
+    len = 0;
+    size_t readLen;
+    ret = pppStream->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 = pppStream->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 = pppStream->read((uint8_t*)buf, &len, 32, 0);
+            DBG("Got %s[len %d]", buf, len);
+        } while( (ret == OK) && (len > 0) );
+        return NET_CONN;
+    }
+
+    DBG("Transport link open");
+    if(datarate != 0)
+        DBG("Datarate: %d bps", datarate);
+    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;
+int PPPIPInterface::escape(void) {
+    DBG("Sending %s", ESCAPE_SEQ);
+    Thread::wait(1000);
+    int ret = pppStream->write((uint8_t*)ESCAPE_SEQ, strlen(ESCAPE_SEQ), osWaitForever);
+    Thread::wait(1000);
+    if( ret != OK )
+      return NET_UNKNOWN;
+    return OK;
+}
+
+int PPPIPInterface::connect(const char* user, const char* pw) {
+    
+    DBG("Trying to connect with PPP");
+    
+    // Init the lWIP Stacks
+    stackInits(user,pw);
+    
+    // Clear the line
+    cleanupLink();
+    
+    // Do the dialing
+    dial();
+    
+    // Launch the ppp session
+    pppSession = pppOverSerialOpen(this, PPPIPInterface::linkStatusCb, this);
+    DBG("PPP over serial opening returned = %d, pppSession");
+    if (pppSession >= 0) {
+        // the thread was successfully started.
+        int retries = 600; // Approx (600*100ms) = 60s
+        while (!connected && (retries-- > 0)) {
+            Thread::wait(100);
+        }
+        
+        if (retries!=0) {
+            // We are connected on lwIP over PPP!
+            DBG("Got Connected");
+            return OK;
+        } else {
+            DBG("Got a Timeout");
+            return NET_UNKNOWN;
+        }    
+    }else {
+        DBG("Could not get ppp session");
+        return NET_UNKNOWN;
+    }
+}
+
+int PPPIPInterface::disconnect() {
+    DBG("Do something on ppp stack and close the session");
+    pppClose(pppSession);
+    escape();
+    cleanupLink();
+    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;
-  }
+void PPPIPInterface::setConnected(bool val) {
+    connected = val;
+}
+
+bool PPPIPInterface::isConnected(void) {
+    return connected;
 }
 
-/*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:
+int PPPIPInterface::cleanupLink() {
+    int ret;
+    char buf[32];
+    size_t len;
+
+    do { //Clear buf
+        ret = pppStream->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);
+    
+    // Here we could need to pass the ATStream to hangup
+    IOStream *hangupPort = pppStream;   
+    ret = hangupPort->write((uint8_t*)HANGUP_CMD, strlen(HANGUP_CMD), osWaitForever);
+    if( ret != OK )
         return NET_UNKNOWN;
-      }
-  }
-  else
-  {
-    if(m_pppd == -1)
-    {
-      return NET_INVALID;
+
+    size_t readLen;
+
+    //Hangup
+    DBG("Expect %s", HANGUP_CMD);
+    
+    len = 0;
+    while( len < strlen(HANGUP_CMD) ) {
+        ret = hangupPort->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 = hangupPort->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 = pppStream->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);
     }
-    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;
+
+    buf[len]=0;
+
+    DBG("Got %s[len %d]", buf, len);
+
+    do { //Clear buf
+        ret = pppStream->read((uint8_t*)buf, &len, 32, 100);
+        if(ret == OK) {
+            buf[len] = '\0';
+            DBG("Got %s", buf);
+        }
+    } while( (ret == OK) && (len > 0) );
+
+    return OK;
+}
+
+// IP Stuffs
+char *PPPIPInterface::getIPAddress(void) {
+    return ipAddress;
+}
+
+void PPPIPInterface::setIPAddress(char *ip) {
+    strcpy(ipAddress,ip);
+}
+
+// PPP Stuffs
+extern "C" {
+    u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len) {
+        //DBG("LEN %d",len);
+        //DBG_MEMDUMP("IN",(const char*)data,len);
+        PPPIPInterface* pIf = (PPPIPInterface*)fd;
+        USBSerialStream *s = pIf->pppStream;
+        int ret = s->write(data, len, osWaitForever); //Blocks until all data is sent or an error happens
+        //DBG("sio_write OUT");
+        if(ret != OK) {
+            return 0;
+        }
+        return len;
+    }
+    
+    u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len) {
+        //DBG("sio_read");
+        PPPIPInterface* pIf = (PPPIPInterface*)fd;
+        size_t readLen;
+        int ret = pIf->pppStream->read(data, &readLen, len, osWaitForever); //Blocks until some data is received or an error happens
+        if(ret != OK) {
+            return 0;
+        }
+        return readLen;
+    }
+
+    void sio_read_abort(sio_fd_t fd) {
+        //DBG("sio_read_abort");
+        PPPIPInterface* pIf = (PPPIPInterface*)fd;
+        pIf->pppStream->abortRead();
+    }
 }
 
 
-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;
+// LwIP Callbacks
+void PPPIPInterface::tcpipInitDoneCb(void *ctx) {
+    PPPIPInterface *pIf = (PPPIPInterface*)ctx;
+    pIf->ipInitiated = true;
 }
 
-/*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;
+void PPPIPInterface::linkStatusCb(void *ctx, int errCode, void *arg) { 
+    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));
-    //Setup DNS
-    if (addrs->dns1.addr != 0)
-    {
-      dns_setserver(0, (struct ip_addr*)&(addrs->dns1));
-    }
-    if (addrs->dns2.addr != 0)
-    {
-      dns_setserver(1, (struct ip_addr*)&(addrs->dns1));
-    }
-        
-    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"
-{
+    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));
+            //Setup DNS
+            if (addrs->dns1.addr != 0) {
+                //dns_setserver(0, (struct ip_addr*)&(addrs->dns1));
+            }
+            if (addrs->dns2.addr != 0) {
+                //dns_setserver(1, (struct ip_addr*)&(addrs->dns1));
+            }
 
-/**
- * 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;
-}
+            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;
+    }
 
-/**
- * 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;
+    //pIf->m_linkStatusSphre.wait(0); //If previous event has not been handled, "delete" it now
+    //pIf->m_pppErrCode = errCode;
+    //pIf->m_linkStatusSphre.release();
 }
-
-/**
- * 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");
-}
-
-}
-
--- a/PPPIPInterface.h	Fri Feb 20 17:15:55 2015 +0000
+++ b/PPPIPInterface.h	Tue Apr 14 13:27:07 2015 +0000
@@ -1,65 +1,48 @@
-/* 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"
+#include "USBSerialStream.h"
 
-namespace rtos {
-class Semaphore;
-}
-using namespace rtos;
-
-/** Interface using PPP to connect to an IP-based network
- *
- */
-class PPPIPInterface : public LwIPInterface
-{
+class PPPIPInterface {
+private:
+    char ipAddress[16];
+    
+    USBSerialStream* pppStream; //Serial stream
+    
+    int cleanupLink();
+    int pppSession;
+    bool ipInitiated;
+    bool pppInitiated;
+    bool connected;
 public:
-    PPPIPInterface(IOStream* pStream);
+    PPPIPInterface(USBSerialStream* 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;
-
+    
+    void stackInits(const char* user, const char* pw);
+    int dial(void);
+    int escape(void);
+    
+    int connect(const char* user, const char* pw);
+    int disconnect();
+    
+    void setConnected(bool val);
+    bool isConnected(void);
+    
+    // IP stuffs
+    char *getIPAddress(void);
+    void setIPAddress(char *ip);
+    
+    // PPP implementaion
     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);
+
+    // CallBacks
+    static void tcpipInitDoneCb(void *arg);
+    static void linkStatusCb(void *ctx, int errCode, void *arg);
 };
 
 #endif /* PPPIPINTERFACE_H_ */
--- a/PyrnUSBModem.cpp	Fri Feb 20 17:15:55 2015 +0000
+++ b/PyrnUSBModem.cpp	Tue Apr 14 13:27:07 2015 +0000
@@ -1,7 +1,11 @@
 
-#include "dbg.h"
 #include "PyrnUSBModem.h"
-#include "HuaweiUSBModemInitializer.h"
+
+#define __DEBUG__ 5
+#ifndef __MODULE__
+#define __MODULE__ "PyrnUSBModem.cpp"
+#endif
+#include "MyDebug.h"
 
 // Command Processors
 
@@ -12,18 +16,18 @@
     PIN_STATUS getStatus() { return status; }
 private:
     virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line) {
-        USB_DBG("GOT %s",line);
+        DBG("GOT %s",line);
         if(!strncmp(line, "+CPIN: READY",12)) {
             status = STATUS_READY; 
-            USB_DBG("STATUS_READY");
+            DBG("STATUS_READY");
         } else if(!strncmp(line, "+CPIN: SIM PIN",14)) {
             status = STATUS_SIMPIN;
-            USB_DBG("STATUS_SIMPIN");
+            DBG("STATUS_SIMPIN");
         }else if(!strncmp(line, "+CPIN: SIM PUK",14)) {
             status = STATUS_SIMPUK;
-            USB_DBG("STATUS_SIMPUK");
+            DBG("STATUS_SIMPUK");
         } else
-            USB_DBG("STATUS_NONE");
+            DBG("STATUS_NONE");
         return OK;
     }
     virtual int onNewEntryPrompt(ATCommandsInterface* pInst) { return OK; }
@@ -117,135 +121,210 @@
     volatile bool valid;
 };
 
-PyrnUSBModem::PyrnUSBModem(USBHost *host): 
+// ==================== MODEM =====================
+
+PyrnUSBModem::PyrnUSBModem():
+        initialiser(USBHost::getHostInst()),
         dongle(),   
         atStream(dongle.getSerial(3)),
-        pppStream(dongle.getSerial(3)),
+        pppStream(dongle.getSerial(0)),
         at(&atStream),
-        ppp(&pppStream),
+        ppp(&pppStream), 
         atOpen(false),
-        pppOpen(false) {
-    // If we support more dongle add the initializer here.
-    // furthermore add dongle specific initialisation int init().
-    HuaweiE372USBModemInitializer *huaweie372Initializer = new HuaweiE372USBModemInitializer(host);
-    dongle.addInitializer(huaweie372Initializer);
+        simReady(false),
+        pppOpen(false),
+        ipInit(false) {
+    DBG("Add E372 dongle initializer");
+    dongle.addInitializer(&initialiser);
 }
 
 bool PyrnUSBModem::init() {
-
+    int ret = 0;
+    
     if(!dongle.connected()){
-        while(!dongle.connected()) {
-          USB_INFO("Dongle try connect");
-          dongle.tryConnect();
-          Thread::wait(10);
+        bool detectConnectedModem = false;
+        for (int x=0; x<5;x++){
+            DBG("Trying to connect the dongle");
+            dongle.tryConnect();
+            if (dongle.connected()) {
+                DBG("Great the dongle is connected - I've tried %d times to connect", x);
+                detectConnectedModem = true;
+                break;                              // Break out of the for loop once the dongle is connected - otherwise try for a while more
+            }
+            Thread::wait(7000);
         }
-        if(!dongle.connected())
+        if (!detectConnectedModem) {
+            // OK we got this far - so give up trying and let someone know you can't see the modem
+            ERR("There is no dongle pluged into the board, or the module does not respond. Is the module/modem switched on?");
             return false;
-    } else 
-        USB_INFO("Dongle is already connected ... continue");
-
-    if(atOpen) {
-        USB_INFO("Stream is already opened");
-        return true;
+        }
+    } else {
+        INFO("Dongle is already connected ... continue");
     }
 
-    USB_INFO("Starting AT thread if needed");
-    int ret = at.open();
-    if(ret) {
-        USB_ERR("Opening AT failed");
-        return false;
-    }
-
-    USB_INFO("Sending initialisation commands");
-    ret = at.init();
-    if(ret) {
-        USB_ERR("Initialisation AT failed");
-        return false;
-    }
-
-    if(dongle.getDongleType() == WAN_DONGLE_TYPE_HUAWEI_E372) {
-        USB_INFO("Using a Vodafone E372 Dongle");
-        // Specific dongle initisation
-        ret = at.executeSimple("AT", NULL,5000);
-        if(ret != OK){
-            USB_ERR("AT Simple command ERROR");
+    if(atOpen) {
+        INFO("Stream is already opened go to SIM Check");
+    } else {
+        
+        INFO("Starting AT thread if needed");
+        ret = at.open();
+        if(ret) {
+            ERR("Opening AT failed");
             return false;
-        } else {
-            USB_INFO("AT Simple command gone well!!");
+        }
+    
+        INFO("Sending initialisation commands");
+        // Echo 1
+        // Format CRLF
+        // Unsollicited Codes disabled
+        ret = at.init("ATZ E1 V1 ^CURC=0");
+        if(ret) {
+            ERR("Initialisation AT failed");
+            return false;
         }
-    } else  {
-        USB_WARN("Using an Unknown Dongle");
+        
+        if(dongle.getDongleType() == WAN_DONGLE_TYPE_HUAWEI_E372) {
+            INFO("Using a Vodafone E372 Dongle");
+            ERR("Send CMEE cmd ...");
+            ret = at.executeSimple("AT+CMEE=1",NULL,5000);
+            if(ret != OK) {
+                ERR("CMEE cmd failed");
+                return false;
+            }
+        } else  {
+            WARN("Using an Unknown Dongle.. do specific init");
+        }
+        
+        atOpen = true;
     }
 
     ATCommandsInterface::ATResult result;
 
-    // SIM PIN Stuff here
-    bool pin = false;
-    int retries = 3;
-    do {
-        CPINProcessor cpinProcessor;
-        USB_INFO("Check CPIN STATE");
-        ret = at.execute("AT+CPIN?", &cpinProcessor, &result,5000);
-        USB_INFO("Result of command: Err code=%d\n", ret);
-        USB_INFO("ATResult: AT return=%d (code %d)\n", result.result, result.code);
-        if(ret == OK) {
-            if(cpinProcessor.getStatus() == CPINProcessor::STATUS_READY) {
-                USB_INFO("ME PIN READY\n");
-                pin = true;
-                break;
-            } else if (cpinProcessor.getStatus() == CPINProcessor::STATUS_SIMPIN)  {
-                USB_INFO("ME SIM PIN NEEDED\n");
-                ret = at.executeSimple("AT+CPIN=\"0000\"", NULL,5000);
-                if(ret != OK){
-                    USB_ERR("CPIN ERROR ... do not retry");
+    if(!simReady){
+        // SIM PIN Stuff here
+        int retries = 3;
+        do {
+            CPINProcessor cpinProcessor;
+            INFO("Check CPIN STATE");
+            ret = at.execute("AT+CPIN?", &cpinProcessor, &result,5000);
+            //INFO("Result of command: Err code=%d", ret);
+            //INFO("ATResult: AT return=%d (code %d)", result.result, result.code);
+            if(result.code == 14) {
+                 WARN("SIM IS Busy retry");
+                 retries++;
+                 Thread::wait(500);
+            } else if(ret == OK) {
+                if(cpinProcessor.getStatus() == CPINProcessor::STATUS_READY) {
+                    INFO("ME PIN READY");
+                    simReady = true;
+                    break;
+                } else if (cpinProcessor.getStatus() == CPINProcessor::STATUS_SIMPIN)  {
+                    INFO("ME SIM PIN NEEDED");
+                    ret = at.executeSimple("AT+CPIN=\"0000\"",NULL,5000);
+                    if(ret != OK){
+                        ERR("CPIN ERROR ... do not retry");
+                        break;
+                    } else {
+                        INFO("CPIN OK");
+                    }
+                } else if (cpinProcessor.getStatus() == CPINProcessor::STATUS_SIMPUK) {
+                    INFO("CPIN IS PUKED");
                     break;
                 } else {
-                    USB_INFO("CPIN OK");
+                    ERR("UNKNOWN STATUS");
+                    break;
                 }
-            } else if (cpinProcessor.getStatus() == CPINProcessor::STATUS_SIMPUK) {
-                USB_INFO("CPIN IS PUKED");
-                break;
             } else {
-                USB_ERR("UNKNOWN STATUS");
+                INFO("SIM PIN ERROR: SIM Probably not inserted");
                 break;
             }
-        } else {
-            USB_INFO("SIM PIN ERROR: SIM Probably not inserted\n");
-            break;
+            retries--;
+        } while(retries);
+        
+        if(!simReady) {
+            ERR("Couldn't pin unlock ...");
+            return false;
         }
-        retries--;
-    } while(retries);
+    } else {
+        INFO("SIM PIN have been unlocked somewhere!");
+    }
     
-    if(!pin) {
-        USB_ERR("Couldn't pin unlock ...");
-        return false;
-    }
-
     //Wait for network registration
     CREGProcessor cregProcessor;
     do {
-        USB_INFO("Waiting for network registration");
+        INFO("Waiting for network registration");
         ret = at.execute("AT+CREG?", &cregProcessor, &result);
-        USB_INFO("Result of command: Err code=%d\n", ret);
-        USB_INFO("ATResult: AT return=%d (code %d)\n", result.result, result.code);
+        //INFO("Result of command: Err code=%d", ret);
+        //INFO("ATResult: AT return=%d (code %d)", result.result, result.code);
         if(cregProcessor.getStatus() == CREGProcessor::STATUS_REGISTERING) {
-            Thread::wait(3000);
+            Thread::wait(500);
         }
     } while(cregProcessor.getStatus() == CREGProcessor::STATUS_REGISTERING);
     if(cregProcessor.getStatus() == CREGProcessor::STATUS_FAILED) {
-        USB_ERR("Registration denied");
+        ERR("Registration denied");
         return false;
     }
-    
-    atOpen = true;
 
     return true;
 }
 
-bool PyrnUSBModem::isConnected(void) {
+bool PyrnUSBModem::attached(void) {
     return dongle.connected();
 }
 
+bool PyrnUSBModem::pppConnected(void) {
+    return ppp.isConnected();
+}
+
+/*
 WANDongleSerialPort *PyrnUSBModem::getAtInterface(int i) {
     return dongle.getWANSerial(i);
+}*/
+
+int PyrnUSBModem::connect(const char* apn, const char* user, const char* password) {
+    int ret;
+
+    if(!init()) {
+        ERR("Modem could not register");
+        return -1;
+    }
+       
+    ATCommandsInterface::ATResult result;
+
+    if(apn != NULL) {
+        char cmd[48];
+        int tries = 30;
+        DBG("Setting APN to %s", apn);
+        sprintf(cmd, "AT+CGDCONT=1,\"IP\",\"%s\"", apn);
+        do {//Try 30 times because for some reasons it can fail *a lot* with the K3772-Z dongle
+            ret = at.executeSimple(cmd, &result);
+            //DBG("Result of command: Err code=%d", ret);
+            if(ret)
+                Thread::wait(500);
+        } while(ret && --tries);
+        // DBG("ATResult: AT return=%d (code %d)", result.result, result.code);
+    }
+        
+    DBG("Connecting PPP");
+    ret = ppp.connect(user, password);
+    DBG("Result of connect: Err code=%d", ret);
+    
+    return ret;
+}
+
+int PyrnUSBModem::disconnect() {
+    DBG("Disconnecting from PPP");
+    int ret = ppp.disconnect();
+    if(ret) {
+        ERR("Disconnect returned %d, still trying to disconnect", ret);
+    }
+
+    Thread::wait(500);
+
+    return OK;
+}
+
+char* PyrnUSBModem::getIPAddress() {
+    // return NULL;//ppp.getIPAddress();
+    return ppp.getIPAddress();
 }
\ No newline at end of file
--- a/PyrnUSBModem.h	Fri Feb 20 17:15:55 2015 +0000
+++ b/PyrnUSBModem.h	Tue Apr 14 13:27:07 2015 +0000
@@ -3,26 +3,42 @@
 #define PYRN_USB_MODEM_H
 
 #include "mbed.h"
+
 #include "USBHost/USBHost3GModule/WANDongle.h"
 #include "USBSerialStream.h"
 #include "ATCommandsInterface.h"
 #include "PPPIPInterface.h"
 
+#include "HuaweiE372DongleInitializer.h"
+
 class PyrnUSBModem {
 private:
+    HuaweiE372DongleInitializer initialiser;
     WANDongle dongle;
+    
     USBSerialStream atStream;
     USBSerialStream pppStream;
+    
     ATCommandsInterface at;
     PPPIPInterface ppp;
+    
     bool atOpen;
+    bool simReady;
     bool pppOpen;
+    bool ipInit;  
 public:
-    PyrnUSBModem(USBHost *h);
+    PyrnUSBModem();
     bool init();
-    bool isConnected(void);
-    void testAT(void);
+    
     WANDongleSerialPort *getAtInterface(int i);
+
+    bool attached(void);
+    bool pppConnected(void);
+
+    int connect(const char* apn, const char* user, const char* password);
+    int disconnect(void);
+
+    char* getIPAddress(void);
 };
 
 #endif
\ No newline at end of file
--- a/USBSerialStream.cpp	Fri Feb 20 17:15:55 2015 +0000
+++ b/USBSerialStream.cpp	Tue Apr 14 13:27:07 2015 +0000
@@ -17,10 +17,15 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#include <stdio.h>
+#include <cstdio>
 
 #include "USBSerialStream.h"
 
+#define __DEBUG__ 0
+#ifndef __MODULE__
+#define __MODULE__ "USBSerialStream.cpp"
+#endif
+#include "MyDebug.h"
 
 USBSerialStream::USBSerialStream(IUSBHostSerial& serial) : m_serial(serial), m_serialTxFifoEmpty(true),
 m_availableSphre(1), m_spaceSphre(1), m_inBuf()
@@ -39,11 +44,11 @@
 //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*/)
 {
-  USB_DBG("Trying to read at most %d chars", maxLength);
+  DBG("Trying to read at most %d chars", maxLength);
   int ret = waitAvailable(timeout);
   if(ret)
   {
-    USB_WARN("Error %d while waiting for incoming data", ret);
+    WARN("Error %d while waiting for incoming data", ret);
     return ret;
   }
   int a = available(); //Prevent macro issues
@@ -57,7 +62,7 @@
     buf++;
   }
   setupReadableISR(true);
-  USB_DBG("Read %d chars successfully", *pLength);
+  DBG("Read %d chars successfully", *pLength);
   return OK;
 }
 
@@ -78,19 +83,19 @@
     return OK;
   }
 
-  USB_DBG("Waiting for data availability %d ms (-1 is infinite)", timeout);
+  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)
   {
-    USB_DBG("Timeout");
+    DBG("Timeout");
     return NET_TIMEOUT;
   }
   if(!m_inBuf.available()) //Even if abort has been called, return that data is available
   {
-    USB_DBG("Aborted");
+    DBG("Aborted");
     return NET_INTERRUPTED;
   }
-  USB_DBG("Finished waiting");
+  DBG("Finished waiting");
   while( m_availableSphre.wait(0) > 0 ); //Clear the queue as data is available
   return OK;
 }
@@ -103,7 +108,7 @@
   }
   else
   {
-    USB_DBG("Serial is readable"); ;
+    DBG("Serial is readable"); ;
   }
   return OK;
 }
@@ -126,18 +131,18 @@
 //0 for non-blocking (returns immediately), -1 for infinite blocking
 /*virtual*/ int USBSerialStream::write(uint8_t* buf, size_t length, uint32_t timeout/*=-1*/)
 {
-  USB_DBG("Trying to write %d chars", length);
+  DBG("Trying to write %d chars", length);
   do
   {
     int ret = waitSpace(timeout);
     if(ret)
     {
-      USB_WARN("Error %d while waiting for space", ret);
+      WARN("Error %d while waiting for space", ret);
       return ret;
     }
     int s = space(); //Prevent macro issues
     int writeLen = MIN( s, length );
-    USB_DBG("Writing %d chars", writeLen);
+    DBG("Writing %d chars", writeLen);
     setupWriteableISR(false);
     while(writeLen)
     {
@@ -154,7 +159,7 @@
     setupWriteableISR(true);
   } while(length);
 
-  USB_DBG("Write successful");
+  DBG("Write successful");
   return OK;
 }
 
@@ -175,16 +180,16 @@
     return OK;
   }
 
-  USB_DBG("Waiting for data space %d ms (-1 is infinite)", timeout);
+  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)
   {
-    USB_DBG("Timeout");
+    DBG("Timeout");
     return NET_TIMEOUT;
   }
   if(!space()) //Even if abort has been called, return that space is available
   {
-    USB_DBG("Aborted");
+    DBG("Aborted");
     return NET_INTERRUPTED;
   }
   while( m_spaceSphre.wait(0) > 0); //Clear the queue as space is available
--- a/USBSerialStream.h	Fri Feb 20 17:15:55 2015 +0000
+++ b/USBSerialStream.h	Tue Apr 14 13:27:07 2015 +0000
@@ -21,8 +21,6 @@
 #define USBSERIALSTREAM_H_
 
 #include "rtos.h"
-
-#include "dbg.h"
 #include "core/IOStream.h"
 #include "core/MtxCircBuffer.h"
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/IOStream.h	Tue Apr 14 13:27:07 2015 +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	Tue Apr 14 13:27:07 2015 +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	Tue Apr 14 13:27:07 2015 +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/errors.h	Tue Apr 14 13:27:07 2015 +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	Tue Apr 14 13:27:07 2015 +0000
@@ -0,0 +1,58 @@
+/* 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"
+
+//Utility macros
+#define MIN(x,y) (((x)<(y))?(x):(y))
+#define MAX(x,y) (((x)>(y))?(x):(y))
+
+#endif /* FWK_H_ */