Vodafone K3770/K3772-Z modems driver & networking library

Dependencies:   Socket USBHostWANDongle lwip-sys lwip

Dependents:   VodafoneUSBModemHTTPClientTest VodafoneUSBModemNTPClientTest VodafoneUSBModemSMSTest VodafoneUSBModemUSSDTest ... more

Fork of VodafoneUSBModem_bleedingedge by Donatien Garnier

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

K3770

More details and instructions can be found here.

Files at this revision

API Documentation at this revision

Comitter:
ashleymills
Date:
Wed Jan 09 16:13:50 2013 +0000
Parent:
78:f0cb615d0074
Child:
80:c0e63c16306e
Commit message:
Experimental MU509 Support

Changed in this revision

USBHostWANDongle.lib Show annotated file Show diff for this revision Revisions of this file
VodafoneUSBModem.cpp 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
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
sms/SMSInterface.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/USBHostWANDongle.lib	Wed Dec 19 09:32:58 2012 +0000
+++ b/USBHostWANDongle.lib	Wed Jan 09 16:13:50 2013 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/ashleymills/code/USBHostWANDongle/#8f2d9a244224
+http://mbed.org/users/ashleymills/code/USBHostWANDongle/#f4b676f61906
--- a/VodafoneUSBModem.cpp	Wed Dec 19 09:32:58 2012 +0000
+++ b/VodafoneUSBModem.cpp	Wed Jan 09 16:13:50 2013 +0000
@@ -34,7 +34,7 @@
    m_sms(&m_at),                       // Construct SMSInterface with the ATCommandsInterface
    m_ussd(&m_at),                      // Construct USSDInterface with the ATCommandsInterface
    m_linkMonitor(&m_at),               // Construct LinkMonitor with the ATCommandsInterface
-   m_ppp(&m_pppStream),                // Construct PPPIPInterface with the PPP serial channel
+   m_ppp(&m_pppStream,&m_atStream,&m_at,false), // Construct PPPIPInterface with the PPP serial channel
    m_dongleConnected(false),           // Dongle is initially not ready for anything
    m_ipInit(false),                    // PPIPInterface connection is initially down
    m_smsInit(false),                   // SMSInterface starts un-initialised
@@ -572,6 +572,15 @@
     }
     */
   }
+  else if(m_dongle.getDongleType()== WAN_DONGLE_TYPE_VODAFONEK3773)
+  {
+     INFO("Using a Vodafone K3773 M2M dongle.");
+  }
+  else if(m_dongle.getDongleType()== WAN_DONGLE_TYPE_VODAFONEMU509)
+  {
+     INFO("Using a Huawei MU509 module.");
+     m_ppp.setHangupViaATPort(true);
+  }
   else
   {
     WARN("Using an Unknown Dongle");
--- a/at/ATCommandsInterface.cpp	Wed Dec 19 09:32:58 2012 +0000
+++ b/at/ATCommandsInterface.cpp	Wed Jan 09 16:13:50 2013 +0000
@@ -17,7 +17,7 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#define __DEBUG__  4 //ERR+WARN
+#define __DEBUG__  0 //ERR+WARN
 #ifndef __MODULE__
 #define __MODULE__ "ATCommandsInterface.cpp"
 #endif
@@ -863,6 +863,17 @@
   return OK;
 }
 
+void ATCommandsInterface::pause() {
+   DBG("pausing at commands interface");
+   m_pStream->abortRead();
+   m_processingThread.signal_set(AT_SIG_PROCESSING_STOP);
+}
+
+void ATCommandsInterface::restart() {
+   DBG("restarting AT commands interface");
+   m_processingThread.signal_set(AT_SIG_PROCESSING_START);
+}
+
 void ATCommandsInterface::process() //Processing thread
 {
   DBG("AT Thread started");
--- a/at/ATCommandsInterface.h	Wed Dec 19 09:32:58 2012 +0000
+++ b/at/ATCommandsInterface.h	Wed Jan 09 16:13:50 2013 +0000
@@ -82,6 +82,10 @@
   //Close connection
   int close();
   
+  // pause at processing
+  void pause();
+  void restart();
+  
   bool isOpen();
 
   class ATResult
@@ -146,7 +150,7 @@
   Mutex m_processingMtx;
   Thread m_processingThread;
 
-  Mutex m_eventsMgmtMtx; //Lock events use within the calling thread
+  Mutex m_eventsMgmtMtx; // locks access to event handler management (adding/removing handlers)
   Mutex m_eventsProcessingMtx; //Lock events use within the processing thread
 };
 
--- a/ip/PPPIPInterface.cpp	Wed Dec 19 09:32:58 2012 +0000
+++ b/ip/PPPIPInterface.cpp	Wed Jan 09 16:13:50 2013 +0000
@@ -49,9 +49,24 @@
 #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)
+PPPIPInterface::PPPIPInterface(
+      IOStream* pStream,
+      IOStream* atStream,
+      ATCommandsInterface* pIf,
+      bool hangupViaATPort
+   ) :
+   LwIPInterface(),
+   m_linkStatusSphre(1),
+   m_pppErrCode(0),
+   m_pStream(pStream),
+   m_atStream(atStream),
+   m_streamAvail(true),
+   m_pppd(-1),
+   m_pIf(pIf),
+   m_hangupViaATPort(hangupViaATPort)
 {
-  m_linkStatusSphre.wait();
+
+    m_linkStatusSphre.wait();
 }
 
 /*virtual*/ PPPIPInterface::~PPPIPInterface()
@@ -59,399 +74,385 @@
 
 }
 
+void PPPIPInterface::setHangupViaATPort(bool val) {
+   m_hangupViaATPort = val;
+}
+
 /*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;
+    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;
+    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;
+    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;
-  }
-  
-  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
+    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_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;
-  }
+    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;
+    DBG("disconnect called");
+    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
     }
-    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;
+    
+    if(!m_hangupViaATPort) {
+       DBG("Sending %s", ESCAPE_SEQ);
+       Thread::wait(1000);
+       ret = m_pStream->write((uint8_t*)ESCAPE_SEQ, strlen(ESCAPE_SEQ), osWaitForever);
+       Thread::wait(1000);
+       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);
+    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);
+    
+    // set the port to send the hangup command to, and disable AT thread if necessary
+    IOStream *hangupPort = m_pStream;
+    if(m_hangupViaATPort) {
+       m_pIf->pause();
+       hangupPort = m_atStream;
     }
-  } 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);
+    
+    
+    ret = hangupPort->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 = 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);
     }
-    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);
+
+    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 = 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);
     }
-    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);
+
+    DBG("Got %s[len %d]", buf, len);
+    
+    // restart AT thread
+    if(m_hangupViaATPort) {
+       m_pIf->restart();
+    }
+    
+    //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 = 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);
     }
-    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;
+
+    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;
+    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));
+            }
 
-  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->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();
+    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;
-}
+    /**
+     * 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;
-}
+    /**
+     * 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");
-}
+    /**
+     * 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/ip/PPPIPInterface.h	Wed Dec 19 09:32:58 2012 +0000
+++ b/ip/PPPIPInterface.h	Wed Jan 09 16:13:50 2013 +0000
@@ -25,6 +25,7 @@
 #include "LwIPInterface.h"
 
 #include "lwip/sio.h"
+#include "at/ATCommandsInterface.h"
 
 namespace rtos {
 class Semaphore;
@@ -37,11 +38,15 @@
 class PPPIPInterface : public LwIPInterface
 {
 public:
-    PPPIPInterface(IOStream* pStream);
+    PPPIPInterface(IOStream* pStream, IOStream* atStream, ATCommandsInterface* pIf, bool hangupViaATPort);
+    ATCommandsInterface* m_pIf;
     virtual ~PPPIPInterface();
 
     int init(); //Init PPP-specific stuff, create the right bindings, etc
     int setup(const char* user, const char* pw); //Setup authentication
+    
+    // should the modem hangup via AT port or PPP port? true for AT port
+    void setHangupViaATPort(bool val);
     virtual int connect();
     virtual int disconnect();
 
@@ -53,8 +58,13 @@
     int m_pppErrCode;
 
     IOStream* m_pStream; //Serial stream
+    
+    IOStream* m_atStream;
     bool m_streamAvail;
-
+    
+    // if this is true, then PPP connection must be terminated using AT virtual serial port 
+    // this is usually because the ppp stream doesn't support +++ escape sequence
+    bool m_hangupViaATPort;
     int m_pppd;
 
     friend u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len);
--- a/sms/SMSInterface.cpp	Wed Dec 19 09:32:58 2012 +0000
+++ b/sms/SMSInterface.cpp	Wed Jan 09 16:13:50 2013 +0000
@@ -17,7 +17,7 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#define __DEBUG__ 2
+#define __DEBUG__ 4
 #ifndef __MODULE__
 #define __MODULE__ "SMSInterface.cpp"
 #endif