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:
8:04b6a042595f
Child:
9:3f077dde13c9
Child:
10:21a6f09d5631
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ip/PPPIPInterface.cpp	Tue Jun 26 13:44:59 2012 +0000
@@ -0,0 +1,269 @@
+/* PPPIPInterface.cpp */
+/*
+Copyright (C) 2012 ARM Limited.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#define __DEBUG__ 2 //Maximum verbosity
+#ifndef __MODULE__
+#define __MODULE__ "PPPIPInterface.cpp"
+#endif
+
+#include "core/fwk.h"
+#include "rtos.h"
+
+#include "PPPIPInterface.h"
+
+extern "C" {
+#include "lwip/ip_addr.h"
+#include "lwip/inet.h"
+#include "netif/ppp/ppp.h"
+}
+
+#if NET_PPP
+
+PPPIPInterface::PPPIPInterface(IOStream* pStream) : LwIPInterface(), m_linkStatusSphre(1), m_pppErrCode(0), m_pStream(pStream), m_streamAvail(true), m_pppd(-1)
+{
+  m_linkStatusSphre.wait();
+}
+
+/*virtual*/ PPPIPInterface::~PPPIPInterface()
+{
+
+}
+
+/*virtual*/ int PPPIPInterface::init() //Init PPP-specific stuff, create the right bindings, etc
+{
+  DBG("Initializing LwIP");
+  LwIPInterface::init(); //Init LwIP, NOT including PPP
+  DBG("Initializing PPP");
+  pppInit();
+  DBG("Done");
+  return OK;
+}
+
+int PPPIPInterface::setup(const char* user, const char* pw)
+{
+  DBG("Configuring PPP authentication method");
+  pppSetAuth(PPPAUTHTYPE_ANY, user, pw);
+  DBG("Done");
+  return OK;
+}
+
+/*virtual*/ int PPPIPInterface::connect()
+{
+  DBG("Trying to connect with PPP");
+  m_linkStatusSphre.wait(0);
+  if((m_pppd != -1) && (m_pppErrCode == 0)) //Already connected
+  {
+    return NET_INVALID;
+  }
+  int ret = pppOverSerialOpen(this, PPPIPInterface::linkStatusCb, this);
+  if(ret < 0)
+  {
+    switch(ret)
+    {
+    case PPPERR_OPEN:
+    default:
+      return NET_FULL; //All available resources are already used
+    }
+  }
+  m_pppd = ret; //PPP descriptor
+  m_linkStatusSphre.wait(); //Block indefinitely; there should be a timeout there
+  if(m_pppErrCode != PPPERR_NONE)
+  {
+    m_pppd = -1;
+  }
+  switch(m_pppErrCode)
+  {
+  case PPPERR_NONE: //Connected OK
+    return OK;
+  case PPPERR_CONNECT: //Connection lost
+    return NET_INTERRUPTED;
+  case PPPERR_AUTHFAIL: //Authentication failed
+    return NET_AUTH;
+  case PPPERR_PROTOCOL: //Protocol error
+    return NET_PROTOCOL;
+  default:
+    return NET_UNKNOWN;
+  }
+}
+
+/*virtual*/ int PPPIPInterface::disconnect()
+{
+  int ret = m_linkStatusSphre.wait(0);
+  if(ret > 0) //Already disconnected?
+  {
+    m_pppd = -1; //Discard PPP descriptor
+    switch(m_pppErrCode)
+      {
+      case PPPERR_CONNECT: //Connection terminated
+      case PPPERR_AUTHFAIL: //Authentication failed
+      case PPPERR_PROTOCOL: //Protocol error
+      case PPPERR_USER:
+        return OK;
+      default:
+        return NET_UNKNOWN;
+      }
+  }
+  else
+  {
+    if(m_pppd == -1)
+    {
+      return NET_INVALID;
+    }
+    pppClose(m_pppd);
+    do
+    {
+      m_linkStatusSphre.wait(); //Block indefinitely; there should be a timeout there
+      DBG("Received PPP err code %d", m_pppErrCode);
+    } while(m_pppErrCode != PPPERR_USER);
+    m_pppd = -1; //Discard PPP descriptor
+  }
+  return OK;
+}
+
+/*static*/ void PPPIPInterface::linkStatusCb(void *ctx, int errCode, void *arg) //PPP link status
+{
+  PPPIPInterface* pIf = (PPPIPInterface*)ctx;
+  struct ppp_addrs* addrs = (struct ppp_addrs*) arg;
+
+  switch(errCode)
+  {
+  case PPPERR_NONE:
+    WARN("Connected via PPP.");
+    DBG("Local IP address: %s", inet_ntoa(addrs->our_ipaddr));
+    DBG("Netmask: %s", inet_ntoa(addrs->netmask));
+    DBG("Remote IP address: %s", inet_ntoa(addrs->his_ipaddr));
+    DBG("Primary DNS: %s", inet_ntoa(addrs->dns1));
+    DBG("Secondary DNS: %s", inet_ntoa(addrs->dns2));
+    setConnected(true);
+    setIPAddress(inet_ntoa(addrs->our_ipaddr));
+    break;
+  case PPPERR_CONNECT: //Connection lost
+    WARN("Connection lost/terminated");
+    setConnected(false);
+    break;
+  case PPPERR_AUTHFAIL: //Authentication failed
+    WARN("Authentication failed");
+    setConnected(false);
+    break;
+  case PPPERR_PROTOCOL: //Protocol error
+    WARN("Protocol error");
+    setConnected(false);
+    break;
+  case PPPERR_USER:
+    WARN("Disconnected by user");
+    setConnected(false);
+    break;
+  default:
+    WARN("Unknown error (%d)", errCode);
+    setConnected(false);
+    break;
+  }
+
+  pIf->m_linkStatusSphre.wait(0); //If previous event has not been handled, "delete" it now
+  pIf->m_pppErrCode = errCode;
+  pIf->m_linkStatusSphre.release();
+}
+
+//LwIP PPP implementation
+extern "C"
+{
+
+/**
+ * Writes to the serial device.
+ *
+ * @param fd serial device handle
+ * @param data pointer to data to send
+ * @param len length (in bytes) of data to send
+ * @return number of bytes actually sent
+ *
+ * @note This function will block until all data can be sent.
+ */
+u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len)
+{
+  DBG("sio_write");
+  PPPIPInterface* pIf = (PPPIPInterface*)fd;
+  int ret;
+  if(!pIf->m_streamAvail) //If stream is not available (it is a shared resource) don't go further
+  {
+    return 0;
+  }
+  ret = pIf->m_pStream->write(data, len, osWaitForever); //Blocks until all data is sent or an error happens
+  if(ret != OK)
+  {
+    return 0;
+  }
+  return len;
+}
+
+/**
+ * Reads from the serial device.
+ *
+ * @param fd serial device handle
+ * @param data pointer to data buffer for receiving
+ * @param len maximum length (in bytes) of data to receive
+ * @return number of bytes actually received - may be 0 if aborted by sio_read_abort
+ *
+ * @note This function will block until data can be received. The blocking
+ * can be cancelled by calling sio_read_abort().
+ */
+u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len)
+{
+  DBG("sio_read");
+  PPPIPInterface* pIf = (PPPIPInterface*)fd;
+  int ret;
+  size_t readLen;
+  if(!pIf->m_streamAvail) //If stream is not available (it is a shared resource) don't go further
+  {
+    WARN("EXIT NOT AVAIL");
+    return 0;
+  }
+  ret = pIf->m_pStream->read(data, &readLen, len, osWaitForever); //Blocks until some data is received or an error happens
+  if(ret != OK)
+  {
+    return 0;
+  }
+  DBG("ret");
+  return readLen;
+}
+
+/**
+ * Aborts a blocking sio_read() call.
+ *
+ * @param fd serial device handle
+ */
+void sio_read_abort(sio_fd_t fd)
+{
+  DBG("sio_read_abort");
+  PPPIPInterface* pIf = (PPPIPInterface*)fd;
+  if(!pIf->m_streamAvail) //If stream is not available (it is a shared resource) don't go further
+  {
+    return;
+  }
+  pIf->m_pStream->abortRead();
+  DBG("ret");
+}
+
+}
+
+#endif
+