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.

Revision:
79:a6ac8206a58d
Parent:
38:d19354028042
--- 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");
+    }
 
 }